Super-Simple Includes Documentation

v0.244.0

Atomic Deployments

Super Simple Includes supports flexible deployment patterns for production use cases.

Atomic Deployments with ssi atomic

The ssi atomic command provides zero-downtime deployments using automatic directory naming and symlink updates:

Basic Usage

# Deploy with automatic git hash suffix
                ssi atomic site/ /var/www/production
                # Creates: /var/www/production.abc123456789
                # Updates: /var/www/production -> production.abc123456789
                
                # Deploy with custom suffix type
                ssi atomic site/ /var/www/production --suffix=random --suffix-length=8
                # Creates: /var/www/production.xyz98765
                # Updates: /var/www/production -> production.xyz98765
                

Smart Suffix Selection

The atomic command automatically chooses the best suffix type:

  • Git repository: Uses commit hash (12 characters by default)
  • No git: Uses random alphanumeric string (12 characters by default)
# In a git repository
                ssi atomic site/ /var/www/production
                # β†’ production.abc123456789 (git commit hash)
                
                # Outside git repository
                ssi atomic site/ /var/www/production
                # β†’ production.xyz123456789 (random string)
                

How Atomic Deployments Work

  1. Build Phase: SSI builds your site to a new directory with unique suffix
  2. Verification Phase: The build completes successfully or fails atomically
  3. Switch Phase: The symlink is automatically updated to point to the new directory
  4. Zero Downtime: Users see no interruption during the switch

Advanced Options

# Use git hash with specific length (requires .git in source directory)
                ssi atomic site/ /var/www/production --suffix=git --suffix-length=short
                # β†’ production.abc1234567 (10 characters)
                
                # Use timestamp suffix
                ssi atomic site/ /var/www/production --suffix=timestamp
                # β†’ production.20240819105333123456789
                
                # Preview what would happen
                ssi --dry-run atomic site/ /var/www/production
                

Regular Deployments with ssi deploy

For non-atomic deployments, use the standard deploy command:

# Direct deployment to specific directory
                ssi deploy site/ /var/www/html
                
                # Deploy to versioned directory manually
                ssi deploy site/ "/var/www/app-$(date +%Y%m%d)"
                

Web Server Configuration

Nginx Example

server {
                    listen 80;
                    server_name example.com;
                
                    # Serve from the symlink
                    root /var/www/production;
                
                    location / {
                        try_files $uri $uri/ /index.html;
                    }
                }
                

Apache Example

<VirtualHost *:80>
                    ServerName example.com
                
                    # Serve from the symlink
                    DocumentRoot /var/www/production
                
                    <Directory /var/www/production>
                        Options FollowSymLinks
                        AllowOverride None
                        Require all granted
                    </Directory>
                </VirtualHost>
                

Personal Development Server

For local development with user home directories:

server {
                    listen 8080;
                    server_name localhost;
                
                    # Serve from user's public_html symlink
                    root /home/username/public_html;
                
                    location / {
                        try_files $uri $uri/ /index.html;
                    }
                }
                

Rollback

Since each atomic deployment creates its own directory, rollback is simple:

# List available deployments (look for .suffix directories)
                ls -la /var/www/production.*
                
                # Rollback to specific deployment
                ln -sfn /var/www/production.abc123456789 /var/www/production
                
                # Or rollback to previous deployment automatically
                PREV=$(ls -t /var/www/production.* | sed -n '2p')
                ln -sfn "$PREV" /var/www/production
                

Cleanup

Remove old deployments to save disk space:

# Keep only the 5 most recent deployments
                cd /var/www
                ls -dt production.* | tail -n +6 | xargs rm -rf
                

Preserving Dynamic Files

Use the preserve feature to maintain files across deployments:

# In ssi-config.toml
                [[step]]
                emoji = "πŸ”’"
                path = "preservelist.txt"
                processing = "preserve"
                

Example preservelist.txt:

sitemap.xml
                robots.txt
                uploads/
                logs/
                

Recommended Practices

For Production Deployments

  • Use ssi atomic for zero-downtime deployments
  • Monitor disk space and clean up old deployments regularly
  • Use --dry-run to preview deployments before running them

Development vs Production

# Development: Direct deployment
                ssi deploy site/ output/
                
                # Personal dev server: Deploy to home directory
                ssi atomic site/ ~/public_html
                
                # Staging: Test atomic deployment
                ssi atomic site/ /var/www/staging
                
                # Production: Atomic deployment
                ssi atomic site/ /var/www/production
                

Automation Examples

# CI/CD pipeline deployment
                ssi atomic site/ /var/www/production --suffix=git --suffix-length=12
                
                # With health check
                ssi atomic site/ /var/www/production && curl -f http://localhost/health
                

ssi atomic self-heals if the deployment target directory is deleted between runs (for example, by a cleanup script or disk cleanup). It emits a warning and proceeds automatically, making it safe for unattended cron or CI execution without any extra guard logic.

Production Patterns

These patterns cover best practices for production deployments, building on the techniques from the examples.

Full-Site Architecture

Example 99 demonstrates a complete production site using all SSI features together.

# 1. Page processing
                [[step]]
                emoji = "πŸ“„"
                path = "pages/"
                processing = "page"
                
                # 2. Reusable HTML components
                [[step]]
                emoji = "πŸ“Ž"
                path = "blocks/"
                processing = "include"
                type = "html"
                
                # 3. Content (per-page resolution)
                [[step]]
                emoji = "πŸ“"
                path = "content/"
                processing = "include"
                type = "html"
                
                # 4. Site-wide variables
                [[step]]
                emoji = "πŸ’¬"
                path = "texts/"
                processing = "include"
                type = "plain"
                options = ["inline"]
                

This architecture separates:

  • Structure (pages/) β€” HTML skeleton
  • Components (blocks/) β€” Reusable UI widgets
  • Content (content/) β€” Page-specific content
  • Variables (texts/) β€” Site-wide strings

Directory structure:

site/
                β”œβ”€β”€ ssi-config.toml
                β”œβ”€β”€ pages/
                β”‚   β”œβ”€β”€ index.html
                β”‚   β”œβ”€β”€ about.html
                β”‚   └── details.html
                β”œβ”€β”€ blocks/
                β”‚   β”œβ”€β”€ header.html
                β”‚   β”œβ”€β”€ footer.html
                β”‚   └── nav.html
                β”œβ”€β”€ content/
                β”‚   β”œβ”€β”€ index/          # Per-page content
                β”‚   β”‚   β”œβ”€β”€ hero.html
                β”‚   β”‚   └── features.html
                β”‚   β”œβ”€β”€ about/
                β”‚   β”‚   └── story.html
                β”‚   └── details/
                β”‚       └── info.html
                └── texts/
                    β”œβ”€β”€ site-name.txt
                    β”œβ”€β”€ license-notice.txt
                    └── tagline.txt
                

Try it:

cd examples/99-full-site
                ssi deploy site/ output/
                

Production Configuration Patterns

Validated Assets

Use checksums for critical files:

[[step]]
                emoji = "πŸ“¦"
                path = "assets/"
                processing = "copy"
                options = ["checksum"]
                
                [[step]]
                emoji = "πŸ”€"
                path = "fonts/"
                destination = "fonts"
                processing = "copy"
                

Generate checksums:

xxh3sum assets/* > assets.xxh3
                xxh3sum fonts/* > fonts.xxh3
                

Build Information Footer

Embed build metadata in every page:

[[step]]
                emoji = "πŸ•’"
                processing = "include"
                type = "datetime"
                options = ["inline"]
                
                [[step]]
                emoji = "πŸ”§"
                processing = "include"
                type = "git"
                path = ".git/"
                options = ["inline"]
                
                [[step]]
                emoji = "🌍"
                processing = "include"
                type = "environment"
                path = "allowed-env.txt"
                options = ["inline"]
                

Footer component (blocks/build-info.html):

<footer class="build-info">
                    <p>Built: πŸ•’iso</p>
                    <p>Version: abc123 (main)</p>
                    <p>Build: #🌍BUILD_NUMBER</p>
                </footer>
                

Component Library

SSI’s flat processing means subdirectories are ignored. Use prefixed filenames to organize your components:

blocks/
                β”œβ”€β”€ layout-header.html
                β”œβ”€β”€ layout-footer.html
                β”œβ”€β”€ ui-alert-info.html
                β”œβ”€β”€ ui-card.html
                └── nav-breadcrumb.html
                

Multi-Environment Configuration

Use environment variables for deployment targets:

allowed-env.txt:

DEPLOY_ENV
                API_ENDPOINT
                CDN_URL
                

In templates:

<script>
                    const CONFIG = {
                        environment: '🌍DEPLOY_ENV',
                        api: '🌍API_ENDPOINT',
                        cdn: '🌍CDN_URL'
                    };
                </script>
                

Deploy:

# Production
                DEPLOY_ENV=production \
                API_ENDPOINT=https://api.example.com \
                CDN_URL=https://cdn.example.com \
                ssi deploy site/ production/
                
                # Staging
                DEPLOY_ENV=staging \
                API_ENDPOINT=https://staging-api.example.com \
                CDN_URL=https://staging-cdn.example.com \
                ssi deploy site/ staging/
                

Performance

Incremental Deployments

Preserve dynamically-generated content across rebuilds:

[[step]]
                emoji = "πŸ”’"
                path = "preservelist.txt"
                processing = "preserve"
                

preservelist.txt:

# Search index (generated by external tool)
                search-index.json
                
                # Sitemap (updated separately)
                sitemap.xml
                
                # User uploads
                uploads/*.jpg
                uploads/*.png
                

Security

HTML Escaping

Use appropriate content types:

# Safe: HTML-escaped by default
                [[step]]
                emoji = "πŸ“œ"
                path = "user-content/"
                processing = "include"
                type = "plain"
                
                # Only for developer-controlled content
                [[step]]
                emoji = "πŸ“Ž"
                path = "trusted-blocks/"
                processing = "include"
                type = "html"
                

Environment Variable Allowlist

Never expose secrets:

# Good: build metadata
                APP_VERSION
                BUILD_NUMBER
                DEPLOY_ENV
                
                # Bad: never expose secrets
                # DATABASE_PASSWORD
                # API_KEY
                # SECRET_TOKEN
                

Path Validation

Preserve lists are validated automatically:

# Good
                sitemap.xml
                images/hero.jpg
                
                # Bad (rejected automatically)
                # /etc/passwd          ← Absolute path
                # ../../../secret      ← Path traversal
                

External Paths

Only enable when necessary:

[[step]]
                emoji = "πŸ“š"
                path = "../shared-docs/"
                processing = "include"
                type = "markdown"
                options = ["allow-external-paths"]  # Explicit opt-in
                

Requires CLI flag:

ssi --allow-external-paths deploy site/ output/
                

CI/CD Integration

GitHub Actions

name: Deploy Site
                
                on:
                  push:
                    branches: [main]
                
                jobs:
                  deploy:
                    runs-on: ubuntu-latest
                    steps:
                      - uses: actions/checkout@v3
                
                      - name: Install SSI
                        run: |
                          cargo build --release --target x86_64-unknown-linux-musl
                          cp target/x86_64-unknown-linux-musl/release/ssi /usr/local/bin/
                
                      - name: Generate checksums
                        run: |
                          xxh3sum site/assets/* > site/assets.xxh3
                
                      - name: Deploy site
                        env:
                          BUILD_NUMBER: ${{ github.run_number }}
                          DEPLOY_ENV: production
                        run: |
                          ssi deploy site/ output/
                
                      - name: Upload to server
                        run: |
                          rsync -avz --delete output/ server:/var/www/html/
                

The same pattern adapts to GitLab CI, Codeberg Actions, and other CI systems β€” replace the Actions-specific syntax with the equivalent for your platform.

Deployment Checklist

Before production deployment:

  • All examples tested locally
  • Checksums generated for static assets
  • Environment variables configured
  • Preserve list reviewed (if using preserve)
  • Build info footer added
  • External paths minimized or eliminated
  • No secrets in environment allowlist
  • Link validation passed (ssi validate)
  • No unused files (ssi validate --warn-unused)
  • Tests pass in CI/CD

Common Patterns

Blog

[[step]]
                emoji = "πŸ“„"
                path = "pages/"
                processing = "page"
                
                [[step]]
                emoji = "πŸ“"
                path = "posts/"
                processing = "include"
                type = "markdown"
                options = ["markdown-h2"]  # Shift headers for page structure
                
                [[step]]
                emoji = "πŸ“Ž"
                path = "blocks/"
                processing = "include"
                type = "html"
                

Documentation Site

[[step]]
                emoji = "πŸ“„"
                path = "pages/"
                processing = "page"
                
                [[step]]
                emoji = "πŸ“"
                path = "docs/"
                processing = "include"
                type = "markdown"
                
                [[step]]
                emoji = "πŸ“Ž"
                path = "components/"
                processing = "include"
                type = "html"
                
                [[step]]
                emoji = "πŸ’¬"
                path = "strings.toml"
                processing = "include"
                type = "plain"
                options = ["inline"]
                

Landing Page

[[step]]
                emoji = "πŸ“„"
                path = "pages/"
                processing = "page"
                
                [[step]]
                emoji = "πŸ“Ž"
                path = "sections/"  # Hero, features, testimonials
                processing = "include"
                type = "html"
                
                [[step]]
                emoji = "πŸ’¬"
                path = "copy.toml"  # Marketing copy
                processing = "include"
                type = "plain"
                options = ["inline"]
                
                [[step]]
                emoji = "🎨"
                path = "assets/"
                processing = "copy"