Managing Task Assignment in Agentic Workflows · FrankBoard

How to Set Up a Work Board on a VPS for Maximum Privacy

A production-grade self-hosted work board on a VPS requires three security layers: SSH key authentication to eliminate password-based entry points, UFW firewall rules to expose only essential ports, and a reverse proxy with TLS termination to encrypt all traffic and obscure the application server from direct internet exposure.

How to Set Up a Work Board on a VPS for Maximum Privacy

Why Self-Hosting Demands a Security-First Approach

Self-hosting project management software puts you in control of your data, but that control carries responsibility. Unlike SaaS platforms that manage infrastructure security, a VPS-based deployment requires you to harden every layer from the operating system up to the application. The payoff is substantial: complete data sovereignty, no third-party access, and immunity to vendor policy changes or shutdowns.

FrankBoard and similar self-hosted Kanban tools ship with sensible defaults, but those defaults assume a protected network. Exposing any application directly to the internet without hardening is a liability. The following architecture treats privacy as a system property built through layered defenses.

Securing Server Access with SSH Keys

Password-based SSH authentication is the most common entry point for automated attacks. Eliminating it is the single highest-impact hardening step.

Generate an Ed25519 key pair on your local machine if you haven't already:

ssh-keygen -t ed25519 -C "[email protected]"

Copy the public key to your VPS:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-vps-ip

Then modify /etc/ssh/sshd_config on the server:

Restart the SSH service and verify key-only access in a new terminal before closing your existing session. This prevents lockouts during testing.

For additional protection, configure a hardware security key or use SSH certificates if your team size warrants centralized key management. Store your private key in a hardware token or encrypted vault—never on shared development machines.

Hardening the Network Perimeter with UFW

Uncomplicated Firewall (UFW) provides a manageable interface to iptables. Default-deny policies are essential: block everything, then explicitly permit required traffic.

After SSH key setup, enable UFW with these rules:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp  # Your custom SSH port
sudo ufw allow 80/tcp    # HTTP for certificate validation
sudo ufw allow 443/tcp   # HTTPS for secured application access
sudo ufw enable

Do not expose application ports directly. FrankBoard and comparable tools typically run on internal ports like 8080 or 5000—these should remain bound to localhost or a private Docker network, unreachable from the internet.

For teams with static office IPs, restrict SSH access further:

sudo ufw allow from 203.0.113.0/24 to any port 2222 proto tcp

This geographic or network-based restriction adds defense even if keys are compromised.

Deploying FrankBoard with Docker and PostgreSQL

Containerization simplifies dependency management and enables network isolation. FrankBoard's Docker deployment separates the application from the database on distinct networks.

Create a docker-compose.yml structure:

version: '3.8'

networks:
  frontend:
    driver: bridge
  backend:
    internal: true  # No external access

services:
  db:
    image: postgres:15-alpine
    networks:
      - backend
    environment:
      POSTGRES_USER: frankboard
      POSTGRES_PASSWORD: [generate-strong-password]
      POSTGRES_DB: frankboard
    volumes:
      - postgres_data:/var/lib/postgresql/data

  app:
    image: frankboard/frankboard:latest
    networks:
      - frontend
      - backend
    environment:
      DATABASE_URL: postgresql://frankboard:[password]@db:5432/frankboard
    depends_on:
      - db
    # No ports exposed to host—reverse proxy connects via Docker network

volumes:
  postgres_data:

The critical privacy element: the app service publishes no host ports. Communication flows exclusively through the frontend network to your reverse proxy, while the database remains on the isolated backend network.

Generate database credentials with a password manager or openssl rand -base64 32. Rotate these quarterly or on team member departures.

Implementing a Reverse Proxy with TLS Termination

A reverse proxy serves as the controlled entry point, handling TLS encryption, request routing, and additional hardening headers. Two solid options exist: Nginx and Traefik.

Nginx Configuration

Nginx excels when you need explicit control over every directive. Install the Nginx package, then create a site configuration:

server {
    listen 80;
    server_name board.yourdomain.com;
    return 301 https://$server_name$request_uri;  # Force HTTPS
}

server {
    listen 443 ssl http2;
    server_name board.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/board.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/board.yourdomain.com/privkey.pem;
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;

    # Modern security headers
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    location / {
        proxy_pass http://frankboard_app:8080;  # Docker service name
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_hide_header X-Powered-By;
    }
}

Obtain certificates via Certbot with DNS validation or HTTP-01 challenge. DNS validation is preferable for privacy as it doesn't require temporary exposure of port 80.

Traefik Configuration

Traefik suits Docker-centric workflows with automatic service discovery. Its docker-compose integration reduces manual configuration:

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--api.dashboard=false"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@yourdomain.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
    networks:
      - frontend

  app:
    # ... FrankBoard configuration
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frankboard.rule=Host(`board.yourdomain.com`)"
      - "traefik.http.routers.frankboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.frankboard.entrypoints=websecure"

Traefik automatically requests and renews certificates. The Docker socket mount requires careful permissions—never expose it to untrusted containers.

Enforcing Additional Application-Level Protections

Network hardening protects the perimeter; application controls protect against credential abuse and session hijacking.

Authentication hardening for FrankBoard: - Enforce strong passwords via the administrative settings - Enable two-factor authentication if available - Review active sessions regularly and terminate unknown entries - Create role-based access: administrators manage configuration, members access only relevant projects

Session management: - Configure short session timeouts for shared workstations - Use httpOnly and secure cookie flags (handled automatically when X-Forwarded-Proto is set correctly)

Audit logging: - Mount the application logs directory to persistent storage - Forward logs to a centralized system or SIEM for anomaly detection - Review failed login patterns weekly

Maintaining Privacy Through Ongoing Hygiene

Security at setup degrades without maintenance. Establish these practices:

Automated updates: Subscribe to FrankBoard release notifications and PostgreSQL security advisories. Test updates in a staging environment before production deployment. Docker image updates apply with docker-compose pull && docker-compose up -d.

Backup encryption: Encrypt database dumps before off-site storage. Use restic, BorgBackup, or similar tools with client-side encryption. Store encryption keys separately from backup destinations.

Certificate monitoring: TLS certificates expire. Automated renewal fails silently if DNS or validation endpoints change. Monitor with simple health checks or certificate transparency logs.

Network monitoring: Install fail2ban to block repeated SSH or HTTP probing. Review UFW logs monthly for patterns suggesting targeted attention.

Principle of least privilege: Each team member receives exactly the access required. Remove accounts promptly on departure. Rotate shared service credentials quarterly.

Key Takeaways

A properly hardened FrankBoard deployment on a VPS offers privacy guarantees no cloud SaaS can match: your data never leaves infrastructure you control, subject only to your own security practices rather than a vendor's business model or legal jurisdiction.

Original resource: Visit the source site