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 (recommended)
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:
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.
<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:
# 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 --reloadCodality 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:
# Check status
sudo systemctl status codality
# View logs
journalctl -u codality -f
# Restart after config changes
sudo systemctl restart codalityDirectory 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:
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:
curl http://localhost:8000/healthzReturns:
{"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:
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