---
name: nginx
description: Manage nginx web server, vhosts, and static site content on the FreeBSD host. Use when updating clawdie.si, adding new vhosts, configuring SSL, or modifying site content. Triggers on "nginx", "website", "clawdie.si", "update site", "add vhost".
---

# Nginx

Use this skill for web server management and static site updates on the FreeBSD host.

## Scope

This skill covers:

- nginx configuration and vhost management
- Static site content updates (clawdie.si, ai.clawdie.si)
- SSL certificate management (Let's Encrypt via acme.sh)
- Site structure and deployment

This skill does not replace:

- `nginx-glasspane` for the ai.clawdie.si operator surface
- `warden-pf` for firewall rules
- `freebsd-admin` for host-level system changes

## Canonical paths

- nginx config: `/usr/local/etc/nginx/nginx.conf`
- vhosts: `/usr/local/etc/nginx/vhosts/*.conf`
- SSL certs: `/usr/local/etc/nginx/ssl/`
- webroots:
  - clawdie.si: `/usr/local/www/clawdie/`
  - ai.clawdie.si: served by `nginx-glasspane` skill
  - osa.smilepowered.org: `/usr/local/www/osa/`

## Hosted sites

| Domain | Webroot | Vhost | SSL |
| --- | --- | --- | --- |
| clawdie.si | `/usr/local/www/clawdie/` | `clawdie.conf` | Let's Encrypt |
| osa.smilepowered.org | `/usr/local/www/osa/` | `osa.conf` | Let's Encrypt |

## Site structure: clawdie.si

```
/usr/local/www/clawdie/
  index.html              # Main landing page
  css/shared.css          # Shared styles
  docs/index.html         # Documentation page
  guides/
    freebsd-setup.html    # FreeBSD setup guide
    nginx-ssl.html        # Nginx + SSL guide
    stripe-agents.html    # Stripe agents guide
    tailscale-vpn.html    # Tailscale VPN guide
  screenshots/            # Diagnostic screenshots (basic auth protected)
  clawdie-eng-v1.md       # English content source
```

## Protected paths

| Path | Auth | htpasswd file | Credentials |
| --- | --- | --- | --- |
| `/screenshots/` | basic auth | `/usr/local/etc/nginx/screenshots.htpasswd` | in `.env` (`SCREENSHOTS_USER`, `SCREENSHOTS_PASSWORD`) |

### Adding basic auth to a new path

```sh
# 1. generate password hash
openssl passwd -apr1 'your-password'

# 2. write htpasswd file
sudo sh -c 'cat > /usr/local/etc/nginx/newpath.htpasswd << EOF
username:$apr1$hash...
EOF'
sudo chmod 640 /usr/local/etc/nginx/newpath.htpasswd
sudo chown root:www /usr/local/etc/nginx/newpath.htpasswd

# 3. add location block to vhost
#    location /newpath/ {
#        auth_basic "Description";
#        auth_basic_user_file /usr/local/etc/nginx/newpath.htpasswd;
#        try_files $uri $uri/ =404;
#    }

# 4. test and reload
sudo nginx -t && sudo service nginx reload
```

Store credentials in `/home/clawdie/clawdie-ai/.env`. Never in skill files.

## Safe defaults

- Always run `nginx -t` before reloading
- Never reload nginx with a broken config
- Back up vhost configs before modifying
- Keep CSS in shared files, not inline (except index.html which is self-contained)
- Test changes locally before pushing to production

## Workflow

### Updating site content

1. Edit the HTML file directly in the webroot
2. Changes are served immediately (static files, no build step)
3. For structural changes, run `sudo nginx -t` then `sudo service nginx reload`

### Adding a new vhost

1. Create `/usr/local/etc/nginx/vhosts/<domain>.conf`
2. Follow the pattern in `references/vhost-template.md`
3. Run `sudo nginx -t` to validate
4. Run `sudo service nginx reload` to apply

### Strapi admin reverse proxy (optional)

To expose Strapi admin via HTTPS on a subdomain (e.g., `cms.clawdie.si`):

1. Create `/usr/local/etc/nginx/vhosts/cms.conf` using `references/strapi-proxy.md`
2. Strapi runs at `http://192.168.100.3:1337` inside the cms jail
3. Restrict access to Tailscale IPs only
4. Run `sudo nginx -t` then `sudo service nginx reload`

### SSL certificate management

1. Certificates are managed via acme.sh or certbot
2. Certificate paths follow: `/usr/local/etc/nginx/ssl/<domain>/`
3. Each domain has: `fullchain.cer` and `<domain>.key`

## Validation

```sh
# test config
sudo nginx -t

# reload after changes
sudo service nginx reload

# check status
sudo service nginx status

# verify site is serving
curl -sI https://clawdie.si | head -5
```

## Troubleshooting

### nginx won't start

- Check config: `sudo nginx -t`
- Check logs: `tail /var/log/nginx/error.log`
- Check port conflicts: `sockstat -l | grep :80`

### SSL certificate expired

- Check cert dates: `openssl x509 -in /usr/local/etc/nginx/ssl/clawdie/fullchain.cer -noout -dates`
- Renew with acme.sh or certbot

### Changes not visible

- Static files are served immediately — hard refresh the browser
- Check you edited the correct webroot path
