Skip to main content

Overview

Manual deployment gives you full control over the build and runtime environment. This guide covers building from source, managing SSH keys, and running in production.

Prerequisites

  • Go 1.24 or higher
  • Git
  • Linux, macOS, or WSL on Windows
  • SSH client (for testing)

Build from Source

1

Clone the repository

git clone https://github.com/ab-70/ssh-portfolio.git
cd ssh-portfolio
2

Download dependencies

go mod download
This downloads all required Go modules listed in go.mod.
3

Build the binary

go build -o ssh-portfolio .
This creates an executable named ssh-portfolio in the current directory.
4

Verify the build

./ssh-portfolio --help
Or check the binary exists:
ls -lh ssh-portfolio

Optimized Production Build

For production deployments, build with optimizations:
CGO_ENABLED=0 go build -ldflags="-s -w" -o ssh-portfolio .
Build flags explained:
  • CGO_ENABLED=0 - Disable CGO for static binary
  • -ldflags="-s -w" - Strip debug information (smaller binary)
  • -o ssh-portfolio - Output filename

Cross-Platform Builds

GOOS=linux GOARCH=amd64 go build -o ssh-portfolio-linux-amd64 .

Generate SSH Host Keys

SSH Portfolio requires host keys for the SSH server. The application expects keys at .ssh/id_ed25519.
1

Create .ssh directory

mkdir -p .ssh
2

Generate ED25519 key pair

ssh-keygen -t ed25519 -f .ssh/id_ed25519 -N ""
  • -t ed25519 - Use ED25519 algorithm (modern, secure)
  • -f .ssh/id_ed25519 - Output file path
  • -N "" - Empty passphrase (required for automated servers)
3

Verify keys were created

ls -la .ssh/
You should see:
  • id_ed25519 - Private key
  • id_ed25519.pub - Public key
4

Set proper permissions

chmod 600 .ssh/id_ed25519
chmod 644 .ssh/id_ed25519.pub
SSH will refuse to use keys with incorrect permissions for security reasons.
The host key path is configured in main.go:38:
wish.WithHostKeyPath(".ssh/id_ed25519"),

Configure Your Portfolio

Create or edit config.yaml with your information:
name: "Your Name"
tagline: "Your professional tagline"
bio: "A brief bio about yourself"

links:
  - name: "GitHub"
    url: "https://github.com/yourusername"
  - name: "Website"
    url: "https://yourwebsite.com"
See the Configuration Guide for all available options.

Run the Application

Basic Run

./ssh-portfolio
By default, the server starts on 0.0.0.0:2222 (see main.go:25-26).

Custom Port

SSH_PORT=3000 ./ssh-portfolio
The application reads the SSH_PORT environment variable (main.go:27-29):
port := "2222"
if p := os.Getenv("SSH_PORT"); p != "" {
    port = p
}

Background Process

Run in the background with nohup:
nohup ./ssh-portfolio > ssh-portfolio.log 2>&1 &

Test the Connection

ssh localhost -p 2222

Process Management with systemd

For production servers, use systemd to manage the SSH Portfolio service.
1

Create a systemd service file

sudo nano /etc/systemd/system/ssh-portfolio.service
2

Add service configuration

[Unit]
Description=SSH Portfolio Server
After=network.target

[Service]
Type=simple
User=portfolio
Group=portfolio
WorkingDirectory=/opt/ssh-portfolio
Environment="SSH_PORT=2222"
ExecStart=/opt/ssh-portfolio/ssh-portfolio
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=ssh-portfolio

[Install]
WantedBy=multi-user.target
3

Create dedicated user

sudo useradd -r -s /bin/false -d /opt/ssh-portfolio portfolio
4

Set up application directory

sudo mkdir -p /opt/ssh-portfolio/.ssh
sudo cp ssh-portfolio /opt/ssh-portfolio/
sudo cp config.yaml /opt/ssh-portfolio/
sudo cp -r .ssh/id_ed25519* /opt/ssh-portfolio/.ssh/
sudo chown -R portfolio:portfolio /opt/ssh-portfolio
sudo chmod 600 /opt/ssh-portfolio/.ssh/id_ed25519
5

Enable and start the service

sudo systemctl daemon-reload
sudo systemctl enable ssh-portfolio
sudo systemctl start ssh-portfolio
6

Check service status

sudo systemctl status ssh-portfolio

Systemd Service Management

sudo systemctl start ssh-portfolio

Production Considerations

Port Configuration

Running on port 22 requires root privileges. It’s recommended to use a higher port (>1024) or configure port forwarding.
Option 1: Run on high port (recommended)
SSH_PORT=2222 ./ssh-portfolio
Option 2: Use iptables for port forwarding
sudo iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222
Option 3: Use setcap to bind privileged ports
sudo setcap 'cap_net_bind_service=+ep' /opt/ssh-portfolio/ssh-portfolio

Firewall Configuration

Ensure your firewall allows connections:
# UFW
sudo ufw allow 2222/tcp

# iptables
sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT

Monitoring

Monitor your application logs:
# journalctl (systemd)
sudo journalctl -u ssh-portfolio -f

# Log file (nohup)
tail -f ssh-portfolio.log

Updates and Maintenance

To update your deployment:
1

Pull latest changes

git pull origin main
2

Rebuild the binary

go build -o ssh-portfolio .
3

Restart the service

sudo systemctl restart ssh-portfolio

Security Best Practices

  • Run as a non-root user (shown in systemd example)
  • Use restrictive file permissions (600 for private keys)
  • Keep SSH host keys secure and backed up
  • Monitor logs for unusual activity
  • Keep Go and dependencies updated
  • Consider rate limiting at the firewall level

Backup Important Files

Regularly backup:
# Backup configuration and keys
tar czf ssh-portfolio-backup.tar.gz \
  config.yaml \
  .ssh/id_ed25519 \
  .ssh/id_ed25519.pub

Next Steps

Environment Variables

Configure runtime settings

Docker Deployment

Deploy with Docker

Build docs developers (and LLMs) love