Перейти к содержанию

OpenCode Web — Setup Guide for Ubuntu 24.04

Step-by-step guide to deploy the OpenCode web interface behind Nginx with SSL on a fresh Ubuntu 24.04 server. All commands are copy-pasteable. Replace your-server.com with your domain and your-username with your Linux user.


1. Server Preparation

1.1 Update system

sudo apt update && sudo apt upgrade -y

1.2 Configure UFW firewall

sudo ufw allow 22    # SSH
sudo ufw allow 80    # HTTP
sudo ufw allow 443   # HTTPS
sudo ufw enable

1.3 Install and configure fail2ban

sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

1.5 Install unattended-upgrades

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades   # choose "Yes"

2. Install OpenCode via npm (nvm)

Run these commands as your deploy user (your-username), not as root.

2.1 Install nvm and Node.js

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# Restart your shell or source .bashrc, then:
nvm install 24
node --version   # verify: v24.x.x

2.2 Install OpenCode globally

npm install -g opencode-ai
opencode --version   # verify

2.3 Verify the installation

which opencode
# Typically: /home/your-username/.nvm/versions/node/v24.x.x/bin/opencode
opencode --version

3. Create the systemd Service

Create the service file with sudo:

sudo nano /etc/systemd/system/opencode-web.service

Contents (replace your-username and the exact nvm bin path):

[Unit]
Description=OpenCode Web
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=your-username
Environment=HOME=/home/your-username
Environment=OPENCODE_SERVER_USERNAME=your-username
Environment=OPENCODE_SERVER_PASSWORD=your-secure-password
ExecStart=/bin/bash -c 'export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && opencode web --port 5173 --hostname 127.0.0.1'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

The shell wrapper is used instead of a hardcoded binary path. This way the service survives Node.js upgrades via nvm — it always picks up the active version through nvm.sh. Setting HOME is required so nvm can locate its directory.

Reload systemd and test:

sudo systemctl daemon-reload
sudo systemctl start opencode-web
sudo systemctl status opencode-web

4. Configure Nginx

4.1 Install Nginx

sudo apt install nginx -y

4.2 Create the site config

sudo nano /etc/nginx/sites-available/your-server.com
server {
    listen 80;
    listen [::]:80;
    server_name your-server.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name your-server.com;

    # SSL certs — populated by Certbot later
    # ssl_certificate     /etc/letsencrypt/live/your-server.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/your-server.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:5173;

        proxy_http_version 1.1;

        # Standard proxy headers
        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;

        # WebSocket support — REQUIRED, otherwise the UI shows a white screen
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Long timeouts for WebSocket connections
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}

The WebSocket headers are not optional. Without Upgrade, Connection, and the long timeouts, the browser cannot establish a WebSocket connection to the OpenCode backend and the web UI renders as a blank white screen.

4.3 Enable the site

sudo ln -s /etc/nginx/sites-available/your-server.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default   # remove default if present
sudo nginx -t
sudo systemctl reload nginx

4.4 Hide Nginx version

sudo sed -i 's/# server_tokens off;/server_tokens off;/' /etc/nginx/nginx.conf
# Or add it manually inside the http { } block if the line doesn't exist
sudo nginx -t && sudo systemctl reload nginx

4.5 Get SSL with Certbot

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-server.com

Certbot modifies the Nginx config automatically, adding the SSL lines and Let's Encrypt options. Choose redirect (option 2) when asked.

Test auto-renewal:

sudo certbot renew --dry-run

4‑alt. Configure Apache (Alternative)

Skip section 4 and follow this part if you prefer Apache over Nginx.

4‑alt.1 Install Apache and required modules

sudo apt install apache2 -y
sudo a2enmod proxy proxy_http proxy_wstunnel ssl rewrite
sudo systemctl restart apache2

4‑alt.2 Create VirtualHost

sudo nano /etc/apache2/sites-available/your-server.com.conf
<VirtualHost *:80>
    ServerName your-server.com
    Redirect permanent / https://your-server.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName your-server.com

    # SSL certs — populated by Certbot later
    # SSLEngine on
    # SSLCertificateFile    /etc/letsencrypt/live/your-server.com/fullchain.pem
    # SSLCertificateKeyFile /etc/letsencrypt/live/your-server.com/privkey.pem

    # WebSocket upgrade support — REQUIRED, otherwise white screen
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://127.0.0.1:5173/$1 [P,L]

    # Main proxy
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5173/
    ProxyPassReverse / http://127.0.0.1:5173/

    # Long timeouts for WebSocket connections
    ProxyTimeout 86400
</VirtualHost>

The WebSocket rewrite is not optional. The RewriteCond/RewriteRule block routes WebSocket upgrade requests through mod_proxy_wstunnel. Without it the browser cannot establish a WebSocket connection and the UI renders as a blank white screen.

4‑alt.3 Enable the site

sudo a2ensite your-server.com.conf
sudo a2dissite 000-default.conf   # remove default if present
sudo apache2ctl configtest
sudo systemctl reload apache2

4‑alt.4 Hide Apache version (optional)

sudo sed -i 's/ServerTokens.*/ServerTokens Prod/' /etc/apache2/conf-available/security.conf
sudo systemctl reload apache2

4‑alt.5 Get SSL with Certbot

sudo apt install certbot python3-certbot-apache -y
sudo certbot --apache -d your-server.com

Choose redirect (option 2) when asked. Certbot modifies the VirtualHost config and enables SSL automatically.

Test auto-renewal:

sudo certbot renew --dry-run

5. Set Authentication

Authentication is controlled by two environment variables in the systemd unit (already set in step 3):

  • OPENCODE_SERVER_USERNAME — the login username for the web UI
  • OPENCODE_SERVER_PASSWORD — the login password

To change credentials later:

sudo systemctl edit opencode-web

Add or modify Environment= lines under [Service], then:

sudo systemctl daemon-reload
sudo systemctl restart opencode-web

Alternatively, edit the main unit file directly and reload.


6. Enable and Start Everything

sudo systemctl enable opencode-web
sudo systemctl start opencode-web
sudo systemctl reload nginx
sudo systemctl status opencode-web   # should show "active (running)"

Visit https://your-server.com in a browser. You should see the OpenCode login screen.


7. Troubleshooting

White screen / blank page

The WebSocket proxy configuration is missing or incorrect. Verify these four lines are present in the location / block:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

Also check nginx -t && sudo systemctl reload nginx after any edit.

Port 5173 already in use

sudo lsof -i :5173   # see what's listening
sudo systemctl stop opencode-web
sudo systemctl start opencode-web

Service exits with status 127 (command not found)

nvm is not being sourced correctly. Check: - HOME is set in the unit file - The ExecStart line sources $HOME/.nvm/nvm.sh before calling opencode - nvm is installed for the same user that runs the service (User=)

If you installed nvm as a different user, adjust NVM_DIR and User accordingly.

Service exits with status 1 (permission / env)

  • Check the User= line matches the user who owns the nvm directory.
  • Check that HOME= is set — some npm packages require a home directory.
  • Run journalctl -u opencode-web -n 50 for detailed logs.

upstream prematurely closed connection

The OpenCode process crashed. Check journalctl -u opencode-web -f for the stack trace. Common cause: missing or invalid OPENCODE_SERVER_PASSWORD — OpenCode requires both username and password env vars.


Quick Reference

Component Path / Command
systemd unit /etc/systemd/system/opencode-web.service
Nginx site /etc/nginx/sites-available/your-server.com
OpenCode port 127.0.0.1:5173
Service logs journalctl -u openencode-web -f
Nginx logs /var/log/nginx/access.log, /var/log/nginx/error.log
Reload after config change sudo systemctl daemon-reload && sudo systemctl restart opencode-web