Senate

Static Sites

Deploy static websites and Single Page Applications (SPAs)

Static Sites

Deploy static websites, documentation sites, and Single Page Applications (SPAs) with Senate.

Quick Deploy with Nginx

Create service

Go to ServicesNew Service

Enter service name: my-website and click Create

Configure source

  1. Go to the Source tab
  2. Select Docker Image as source type
  3. Enter image: nginx:alpine
  4. Click Save

Add your site

Mount your static files:

Host PathContainer Path
/path/to/site/usr/share/nginx/html:ro

Add domain

Add your domain in the Domains tab.

Deploy

Click Create to deploy.

Pre-built Static Images

Build your own image

Create a Dockerfile:

FROM nginx:alpine
COPY ./dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Build and push:

docker build -t myuser/mysite:latest .
docker push myuser/mysite:latest

Then deploy with the image myuser/mysite:latest.

SPA Configuration

Single Page Applications need special routing:

Nginx config for SPAs

Create nginx.conf:

server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Dockerfile for SPAs

FROM nginx:alpine
COPY dist/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

Framework Examples

React (Vite)

# Build stage
FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Serve stage
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Vue

FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Next.js (Static Export)

For next export:

FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/out /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Astro

FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

Alternative: Caddy

Caddy has simpler config and automatic HTTPS:

Caddyfile

:80 {
    root * /srv
    file_server
    try_files {path} /index.html
}

Dockerfile with Caddy

FROM caddy:alpine
COPY dist/ /srv/
COPY Caddyfile /etc/caddy/Caddyfile

Compression

Enable gzip compression:

Nginx

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1000;

Caddy

Caddy enables compression by default with encode:

:80 {
    root * /srv
    encode gzip
    file_server
}

Security Headers

Add security headers in nginx:

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

CI/CD Integration

GitHub Actions

name: Deploy Static Site

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
      
      - name: Install and build
        run: |
          npm ci
          npm run build
      
      - name: Build and push image
        run: |
          docker build -t myuser/mysite:${{ github.sha }} .
          docker push myuser/mysite:${{ github.sha }}
      
      - name: Deploy to Senate
        run: curl "${{ secrets.SENATE_WEBHOOK }}

Documentation Sites

VitePress

FROM node:20-alpine as build
WORKDIR /app
COPY . .
RUN npm ci && npm run docs:build

FROM nginx:alpine
COPY --from=build /app/docs/.vitepress/dist /usr/share/nginx/html

Docusaurus

FROM node:20-alpine as build
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html

Performance Tips

  1. Enable caching: Set long cache headers for static assets
  2. Use CDN: Put Cloudflare or similar in front
  3. Optimize images: Use WebP, proper sizing
  4. Minimize bundles: Code split, tree shake
  5. Preload critical assets: Use <link rel="preload">

On this page