docs
v0.7.8

Server Setup

Production deployment details: reverse proxy configuration, firewall, permissions, git setup, health checks, and backups.

Note: If you used codality setup, most of this is already configured for you. This page documents what the wizard sets up and how to customize it.

Reverse proxy

Codality listens on HTTP (default port 8000). The setup wizard can configure a reverse proxy with automatic TLS. If you need to customize the configuration, here are the full configs for each supported proxy.

Caddy handles TLS certificates automatically via Let's Encrypt. This is the simplest option.

Caddyfile (typically /etc/caddy/Caddyfile):

codality.example.com {
    reverse_proxy 127.0.0.1:8000
}

That's it. Caddy obtains and renews certificates automatically.

Nginx

The wizard generates a full nginx config at /etc/nginx/sites-available/codality.conf. The key requirements:

nginx
server {
    listen 80;
    server_name codality.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        return 301 https://$server_name$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name codality.example.com;

    ssl_certificate     /etc/letsencrypt/live/codality.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/codality.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }
}
!

Important: proxy_buffering off is required for Server-Sent Events (SSE). Without it, real-time agent activity streaming will not work. The Upgrade and Connection headers enable WebSocket support.

Apache

Required modules: proxy, proxy_http, proxy_wstunnel, ssl, headers, rewrite.

apache
<VirtualHost *:80>
    ServerName codality.example.com
    DocumentRoot /var/www/html

    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/.well-known/
    RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName codality.example.com
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/codality.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/codality.example.com/privkey.pem

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/

    # WebSocket support
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule /(.*) ws://127.0.0.1:8000/$1 [P,L]

    # SSE support
    SetEnv proxy-sendchunked 1
    SetEnv proxy-sendcl 0
</VirtualHost>

Firewall

The setup wizard automatically opens ports 80 and 443 if UFW or firewalld is active. If you're configuring manually:

bash
# UFW (Ubuntu/Debian)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# firewalld (RHEL/CentOS/Fedora)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Codality needs outbound access to:

Host Port Purpose
api.openai.com 443 AI agent API calls
api.sendgrid.com 443 OTP email delivery
api.github.com 443 GitHub integration (if enabled)
api.tavily.com 443 Web search tool (if configured)
Your git remotes 22/443 Pushing code

Systemd service

The setup wizard installs a systemd service with security hardening. The unit file lives at /etc/systemd/system/codality.service.

Key properties:

Setting Value Purpose
User / Group codality Runs as unprivileged system user
ProtectSystem strict Read-only filesystem except explicit paths
ProtectHome true No access to /home
ReadWritePaths /var/lib/codality /etc/codality Only writable paths
NoNewPrivileges true Cannot gain new privileges
PrivateTmp true Isolated /tmp
Restart always Auto-restart on crash
EnvironmentFile /etc/codality/codality.env Configuration source

Useful commands:

bash
# Check status
sudo systemctl status codality

# View logs
journalctl -u codality -f

# Restart after config changes
sudo systemctl restart codality

Directory structure

After setup, Codality uses these paths:

Path Owner Purpose
/usr/local/bin/codality root The binary
/etc/codality/codality.env codality Configuration (mode 0600)
/etc/codality/license.key root License file (mode 0600)
/var/lib/codality/ codality Data directory
/var/lib/codality/codality.db codality SQLite database
/var/lib/codality/worktrees/ codality Git worktrees for agent branches
Project paths codality Your git repositories, configured per project

The worktree directory and project repositories must be on the same filesystem (git worktrees require this).

Permissions

The codality system user (created by the wizard) needs:

  • Read/write access to the data directory (/var/lib/codality)
  • Read/write access to the config directory (/etc/codality)
  • Read/write access to all project repository directories
  • SSH keys or credentials for pushing to git remotes

Since the service runs as the codality user, any repositories it manages must be owned by or accessible to that user.

Git configuration

The agent commits code. Configure a git identity for the codality user:

bash
sudo -u codality git config --global user.name "Codality"
sudo -u codality git config --global user.email "codality@example.com"

For GitHub push access, set up SSH keys for the codality user, or configure the GitHub App integration which handles authentication automatically.

Health check

Codality exposes a health endpoint:

bash
curl http://localhost:8000/healthz

Returns:

json
{"status":"ok","version":"0.7.9","setup_complete":true}

Use this for load balancer health checks or monitoring. The setup_complete field indicates whether the admin account has been created.

Backups

The SQLite database is the primary state to back up. With WAL mode, you can safely copy it while Codality is running:

bash
sqlite3 /var/lib/codality/codality.db ".backup /path/to/backup.db"

Schedule this in a cron job. Project repositories live in their own git repos with full history, so they're backed up by their remotes.

Also consider backing up:

  • /etc/codality/codality.env — your configuration
  • /etc/codality/license.key — your license