Files
portainer-core/docs/code-server-setup.md
T

9.5 KiB

Code-Server Installation Guide

Browser-based VSCode IDE running on host for full system access

Service Type: Host-based (systemd service, not containerized) Purpose: Replace SSH with persistent web-based development environment Access: https://code.schweitz.net (via NPM with SSL)


Why Host-Based?

Unlike other services in this stack, code-server runs directly on the host OS (not in Docker) to provide:

  • Full access to host filesystem and configurations
  • Direct control over systemd services
  • Native Docker CLI access without Docker-in-Docker complexity
  • No permission issues when editing files across SSD/HDD
  • Persistent sessions that survive network disconnections

Installation Steps

1. Install code-server

Run these commands on the tower-of-joy host:

# Download and install code-server (version 4.x)
curl -fsSL https://code-server.dev/install.sh | sh

# Verify installation
code-server --version

2. Create Configuration Directory

# Create config directory
mkdir -p ~/.config/code-server

# Create configuration file
cat > ~/.config/code-server/config.yaml <<'EOF'
bind-addr: 127.0.0.1:8084
auth: password
password: CHANGE_THIS_PASSWORD
cert: false
user-data-dir: /home/jpmschweitzer/docker-data/code-server/user-data
extensions-dir: /home/jpmschweitzer/docker-data/code-server/extensions
EOF

# Create data directories on SSD
mkdir -p /home/jpmschweitzer/docker-data/code-server/{user-data,extensions}

IMPORTANT: Replace CHANGE_THIS_PASSWORD with a strong password. This is a secondary auth layer (NPM will provide the primary authentication).

3. Create Systemd Service

# Create service file
sudo tee /etc/systemd/system/code-server.service > /dev/null <<'EOF'
[Unit]
Description=code-server - Browser-based VSCode IDE
Documentation=https://coder.com/docs/code-server
After=network.target

[Service]
Type=exec
ExecStart=/usr/bin/code-server
Restart=always
User=jpmschweitzer
Group=jpmschweitzer
Environment="PASSWORD_FROM_CONFIG=true"

# Hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=false
ReadWritePaths=/home/jpmschweitzer /mnt/media

[Install]
WantedBy=multi-user.target
EOF

# Reload systemd daemon
sudo systemctl daemon-reload

# Enable and start code-server
sudo systemctl enable code-server
sudo systemctl start code-server

# Check status
sudo systemctl status code-server

4. Verify Local Access

# Test that code-server is running locally
curl -I http://127.0.0.1:8084

# Should return HTTP 302 (redirect to login page)

Service Integration

Uptime Kuma Monitoring

After code-server is running, add it to Uptime Kuma for health monitoring:

  1. Open Uptime Kuma: http://192.168.86.149:3001
  2. Click Add New Monitor
  3. Configure the monitor:

Monitor Settings:

  • Monitor Type: HTTP(s)
  • Friendly Name: Code-Server
  • URL: https://code.schweitz.net
  • Heartbeat Interval: 60 seconds
  • Retries: 3
  • Heartbeat Retry Interval: 60 seconds
  • Accepted Status Codes: 200-299, 302 (redirect to login)
  • Ignore TLS/SSL errors: Disabled (cert should be valid)
  • Tags: Infrastructure, Development
  1. Click Save

The monitor should show "Up" status once code-server is accessible through NPM.

Organizr Dashboard Integration

Add code-server to your Organizr unified dashboard:

  1. Open Organizr: https://home.schweitz.net
  2. Navigate to Settings → Tab Editor
  3. Click Add Tab

Tab Configuration:

  • Tab Name: Code-Server
  • Tab URL: https://code.schweitz.net
  • Category: Infrastructure (or create "Development" category)
  • Icon: fa-code or fa-laptop-code
  • Active: Enabled
  • New Window: Disabled (use iframe)
  1. Homepage Integration (Optional):
    • Go to Settings → Homepage Items
    • Add custom HTML tile:
<div class="homepage-item">
  <a href="https://code.schweitz.net" target="_blank">
    <i class="fa fa-code fa-3x"></i>
    <span>Code-Server</span>
  </a>
</div>
  1. Click Save

The code-server tab will now appear in your Organizr sidebar.


Nginx Proxy Manager Configuration

Create Proxy Host

  1. Open NPM admin interface: http://192.168.86.149:81
  2. Navigate to Hosts → Proxy Hosts → Add Proxy Host

Details Tab:

  • Domain Name: code.schweitz.net
  • Scheme: http
  • Forward Hostname/IP: 192.168.86.149 (or localhost)
  • Forward Port: 8084
  • Block Common Exploits: Enabled
  • Websockets Support: Enabled (critical for code-server)

SSL Tab:

  • SSL Certificate: Request New SSL Certificate
  • Force SSL: Enabled
  • HTTP/2 Support: Enabled
  • HSTS Enabled: Enabled
  • Email: your-email@example.com (for Let's Encrypt)
  • Terms of Service: Agree

Access List Tab:

  • Create new access list: "Code Server Access"
  • Configure basic auth or use NPM's built-in authentication

Advanced Tab (optional):

# Increase timeout for long-running operations
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

# Proper headers for WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Accept-Encoding gzip;

Security Hardening

Firewall Rules

# Ensure port 8084 is NOT exposed to the internet
sudo ufw status

# Port 8084 should only be accessible from localhost
# External access ONLY through NPM on ports 80/443

Authentication Layers

Code-server will have three layers of security:

  1. NPM Access List - Primary authentication via reverse proxy
  2. code-server password - Secondary authentication (from config.yaml)
  3. HTTPS/SSL - Encrypted transport via Let's Encrypt

Create an access list in NPM with:

  • Basic Auth username/password
  • IP whitelist (optional): Restrict to known IPs or Tailscale network
  • Rate limiting: Prevent brute force attacks

Configuration Tips

Extensions to Install

After first login, install these extensions:

# Via code-server CLI
code-server --install-extension ms-python.python
code-server --install-extension ms-azuretools.vscode-docker
code-server --install-extension eamodio.gitlens
code-server --install-extension GitHub.copilot  # If you have Copilot
code-server --install-extension Codeium.codeium  # Free AI assistant alternative

Custom Settings

Edit settings via UI or directly:

nano ~/docker-data/code-server/user-data/User/settings.json

Recommended settings:

{
  "workbench.colorTheme": "Default Dark+",
  "terminal.integrated.defaultProfile.linux": "bash",
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/.git/objects/**": true,
    "**/.venv/**": true
  },
  "editor.formatOnSave": true,
  "files.autoSave": "afterDelay"
}

Maintenance

View Logs

# Systemd logs
sudo journalctl -u code-server -f

# Follow recent logs
sudo journalctl -u code-server --since "10 minutes ago"

Restart Service

sudo systemctl restart code-server

Update code-server

# Re-run installation script
curl -fsSL https://code-server.dev/install.sh | sh

# Restart service to use new version
sudo systemctl restart code-server

Backup Configuration

Configuration is stored in:

  • ~/.config/code-server/config.yaml - Main config
  • ~/docker-data/code-server/user-data/ - Settings, keybindings, snippets
  • ~/docker-data/code-server/extensions/ - Installed extensions

Automated Backups:

The maintenance container backs up code-server configuration nightly at 3 AM to /mnt/media/backups/docker-configs/ with 30-day retention.

After installing code-server, restart the maintenance container to enable backups:

docker restart maintenance

# Verify the mount is accessible
docker exec maintenance ls -la /data/code-server-config

# Manually trigger a backup to test
docker exec maintenance /scripts/backup-configs.sh

# Check backup logs
docker exec maintenance cat /var/log/maintenance/backup-configs.log

Troubleshooting

Service won't start

# Check service status
sudo systemctl status code-server

# Check logs for errors
sudo journalctl -u code-server -n 50

# Verify config file syntax
cat ~/.config/code-server/config.yaml

Can't connect via browser

# Verify code-server is listening
sudo netstat -tlnp | grep 8084

# Check NPM proxy host configuration
# Ensure WebSocket support is enabled
# Verify SSL certificate is valid

Performance issues

# Check system resources
htop

# Monitor code-server process
top -p $(pgrep code-server)

# Increase file watcher limits if needed
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Integration Checklist

  • code-server installed and running via systemd
  • NPM proxy host configured with SSL
  • External access working at https://code.schweitz.net
  • WebSocket connections working (terminal, file watcher)
  • Authentication layers tested (NPM + code-server password)
  • Maintenance container restarted to enable backups
  • Backup tested and verified
  • Uptime Kuma monitoring added
  • Organizr dashboard tab created
  • CONTAINERS.md documentation updated
  • README.md service table updated

References


Created: 2025-11-14 System: tower-of-joy