docs refactor
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 52s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m1s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 5m50s

This commit is contained in:
2025-10-09 18:21:23 -04:00
parent c9a3a21f07
commit ad81d7f3db
39 changed files with 12551 additions and 1037 deletions

View File

@ -0,0 +1,735 @@
---
version: "1.0"
date: "2025-01-15"
author: "DWS Foldsite Team"
title: "Docker Deployment"
description: "Running Foldsite in Docker containers"
summary: "Complete guide to deploying Foldsite with Docker for consistent, isolated, and portable deployments."
quick_tips:
- "Docker ensures consistent environments across development and production"
- "Use docker-compose for easy multi-container setup"
- "Mount content as volumes for live updates without rebuilding"
---
# Docker Deployment
Docker provides isolated, reproducible deployments of Foldsite. Perfect for testing, staging, and production environments.
## Why Docker?
**Benefits:**
- **Consistency** - Same environment everywhere
- **Isolation** - Dependencies don't conflict with system
- **Portability** - Run anywhere Docker runs
- **Easy deployment** - Single command to start
- **Version control** - Docker images are versioned
**Use cases:**
- Team development (everyone has same environment)
- Staging environments before production
- Production deployments
- CI/CD pipelines
- Cloud platform deployments
## Prerequisites
### Install Docker
**macOS:**
```bash
# Download Docker Desktop from docker.com
# Or use Homebrew
brew install --cask docker
```
**Linux (Ubuntu/Debian):**
```bash
# Update package index
sudo apt update
# Install Docker
sudo apt install docker.io docker-compose
# Add your user to docker group
sudo usermod -aG docker $USER
# Log out and back in for group changes
```
**Windows:**
```bash
# Download Docker Desktop from docker.com
# Requires WSL2
```
**Verify installation:**
```bash
docker --version
docker-compose --version
```
## Quick Start with Docker Compose
### Step 1: Create docker-compose.yml
In your Foldsite directory:
```yaml
version: '3.8'
services:
foldsite:
image: python:3.11-slim
container_name: foldsite
working_dir: /app
command: >
sh -c "pip install -r requirements.txt &&
python main.py --config config.toml"
ports:
- "8081:8081"
volumes:
- .:/app
- ./my-site/content:/app/content
- ./my-site/templates:/app/templates
- ./my-site/styles:/app/styles
environment:
- PYTHONUNBUFFERED=1
restart: unless-stopped
```
### Step 2: Create config.toml for Docker
```toml
[paths]
content_dir = "/app/content"
templates_dir = "/app/templates"
styles_dir = "/app/styles"
[server]
listen_address = "0.0.0.0" # Important: bind to all interfaces
listen_port = 8081
admin_browser = false
max_threads = 4
debug = false
access_log = true
```
### Step 3: Start Container
```bash
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
```
Visit `http://localhost:8081` to see your site!
## Building a Custom Docker Image
For production, build a dedicated Foldsite image:
### Create Dockerfile
```dockerfile
# Dockerfile
FROM python:3.11-slim
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements first (for caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY . .
# Create directories for content
RUN mkdir -p /content /templates /styles
# Expose port
EXPOSE 8081
# Run application
CMD ["python", "main.py", "--config", "/app/config.toml"]
```
### Build Image
```bash
# Build image
docker build -t foldsite:latest .
# Tag for versioning
docker tag foldsite:latest foldsite:1.0.0
```
### Run Container
```bash
docker run -d \
--name foldsite \
-p 8081:8081 \
-v $(pwd)/my-site/content:/content \
-v $(pwd)/my-site/templates:/templates \
-v $(pwd)/my-site/styles:/styles \
foldsite:latest
```
## Development with Docker
### Hot Reload Setup
Mount your code as volumes for live updates:
```yaml
# docker-compose.dev.yml
version: '3.8'
services:
foldsite:
build: .
container_name: foldsite-dev
ports:
- "8081:8081"
volumes:
# Mount everything for development
- .:/app
- ./my-site/content:/app/content
- ./my-site/templates:/app/templates
- ./my-site/styles:/app/styles
environment:
- PYTHONUNBUFFERED=1
- FLASK_ENV=development
command: >
sh -c "pip install -r requirements.txt &&
python main.py --config config.toml"
```
**Usage:**
```bash
# Start development environment
docker-compose -f docker-compose.dev.yml up
# Changes to content, templates, and styles appear immediately
# Code changes require restart
```
### Interactive Development
Run commands inside container:
```bash
# Start bash session in running container
docker exec -it foldsite bash
# Inside container, you can:
python main.py --config config.toml
pip install new-package
ls /app/content
```
## Production Docker Setup
### Multi-Stage Build
Optimize image size with multi-stage build:
```dockerfile
# Dockerfile.production
# Stage 1: Build dependencies
FROM python:3.11-slim as builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Stage 2: Runtime
FROM python:3.11-slim
WORKDIR /app
# Copy Python dependencies from builder
COPY --from=builder /root/.local /root/.local
# Copy application
COPY . .
# Create non-root user
RUN useradd -m -u 1000 foldsite && \
chown -R foldsite:foldsite /app
# Switch to non-root user
USER foldsite
# Make sure scripts in .local are usable
ENV PATH=/root/.local/bin:$PATH
EXPOSE 8081
# Use Gunicorn for production
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8081", "main:app"]
```
### Production docker-compose.yml
```yaml
version: '3.8'
services:
foldsite:
build:
context: .
dockerfile: Dockerfile.production
container_name: foldsite-prod
ports:
- "8081:8081"
volumes:
- ./content:/app/content:ro # Read-only
- ./templates:/app/templates:ro
- ./styles:/app/styles:ro
environment:
- PYTHONUNBUFFERED=1
restart: always
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081/"]
interval: 30s
timeout: 10s
retries: 3
```
## Docker Compose Examples
### With Nginx Reverse Proxy
```yaml
version: '3.8'
services:
foldsite:
build: .
container_name: foldsite
expose:
- "8081"
volumes:
- ./content:/app/content:ro
- ./templates:/app/templates:ro
- ./styles:/app/styles:ro
restart: always
nginx:
image: nginx:alpine
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- foldsite
restart: always
```
**nginx.conf:**
```nginx
events {
worker_connections 1024;
}
http {
upstream foldsite {
server foldsite:8081;
}
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://foldsite;
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;
}
# Cache static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_pass http://foldsite;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
}
```
### Multiple Sites
Run multiple Foldsite instances:
```yaml
version: '3.8'
services:
blog:
build: .
ports:
- "8081:8081"
volumes:
- ./blog/content:/app/content
- ./blog/templates:/app/templates
- ./blog/styles:/app/styles
restart: always
portfolio:
build: .
ports:
- "8082:8081"
volumes:
- ./portfolio/content:/app/content
- ./portfolio/templates:/app/templates
- ./portfolio/styles:/app/styles
restart: always
```
## Volume Management
### Content Volumes
**Development** - Mount host directories:
```yaml
volumes:
- ./my-site/content:/app/content
- ./my-site/templates:/app/templates
- ./my-site/styles:/app/styles
```
**Production** - Read-only mounts:
```yaml
volumes:
- ./content:/app/content:ro
- ./templates:/app/templates:ro
- ./styles:/app/styles:ro
```
### Named Volumes
For persistent data:
```yaml
services:
foldsite:
volumes:
- content-data:/app/content
- templates-data:/app/templates
volumes:
content-data:
templates-data:
```
**Backup named volumes:**
```bash
# Backup
docker run --rm \
-v foldsite_content-data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/content-backup.tar.gz -C /data .
# Restore
docker run --rm \
-v foldsite_content-data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/content-backup.tar.gz -C /data
```
## Environment Variables
Pass configuration via environment:
```yaml
services:
foldsite:
environment:
- FOLDSITE_DEBUG=false
- FOLDSITE_PORT=8081
- FOLDSITE_MAX_THREADS=4
```
**Use in config:**
```python
# In a config loader
import os
debug = os.getenv('FOLDSITE_DEBUG', 'false').lower() == 'true'
port = int(os.getenv('FOLDSITE_PORT', '8081'))
```
## Common Docker Commands
### Container Management
```bash
# Start containers
docker-compose up -d
# Stop containers
docker-compose down
# Restart
docker-compose restart
# View logs
docker-compose logs -f
# View logs for specific service
docker-compose logs -f foldsite
# Exec into running container
docker exec -it foldsite bash
# View running containers
docker ps
# View all containers (including stopped)
docker ps -a
```
### Image Management
```bash
# Build image
docker-compose build
# Pull images
docker-compose pull
# List images
docker images
# Remove unused images
docker image prune
# Remove all unused data
docker system prune -a
```
### Debugging
```bash
# Check container logs
docker logs foldsite
# Follow logs
docker logs -f foldsite
# Inspect container
docker inspect foldsite
# View container stats
docker stats foldsite
# Check container health
docker ps --filter health=healthy
```
## Troubleshooting
### Port Already in Use
```
Error: port is already allocated
```
**Solution:** Change port mapping:
```yaml
ports:
- "8082:8081" # Map to different host port
```
### Permission Errors
```
PermissionError: [Errno 13] Permission denied
```
**Solution:** Fix volume permissions:
```bash
# Fix ownership
sudo chown -R $USER:$USER ./my-site
# Or run container as your user
docker run --user $(id -u):$(id -g) ...
```
### Container Won't Start
```bash
# Check logs
docker-compose logs
# Common issues:
# 1. Missing requirements.txt
# 2. Wrong working directory
# 3. Port conflicts
# 4. Volume mount errors
```
### Changes Not Appearing
**Content changes:**
- Should appear immediately (volumes mounted)
- Try hard refresh in browser
**Code changes:**
- Require container restart: `docker-compose restart`
**Template changes:**
- Should appear immediately
- Check volume mounts are correct
### Container Crashes
```bash
# View exit reason
docker ps -a
# Check logs
docker logs foldsite
# Try running interactively
docker run -it foldsite bash
```
## Performance Optimization
### Resource Limits
Limit container resources:
```yaml
services:
foldsite:
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
```
### Build Cache
Speed up builds:
```bash
# Use BuildKit
DOCKER_BUILDKIT=1 docker build .
# Cache from registry
docker build --cache-from myregistry/foldsite:latest .
```
### Layer Optimization
Order Dockerfile for better caching:
```dockerfile
# Dependencies first (change rarely)
COPY requirements.txt .
RUN pip install -r requirements.txt
# Code last (changes often)
COPY . .
```
## CI/CD Integration
### GitHub Actions Example
```yaml
# .github/workflows/docker.yml
name: Build Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build image
run: docker build -t foldsite:${{ github.sha }} .
- name: Test
run: |
docker run -d --name test foldsite:${{ github.sha }}
docker logs test
docker stop test
```
## Cloud Platform Deployment
### Deploy to AWS ECS
```bash
# Build and push to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com
docker tag foldsite:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/foldsite:latest
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/foldsite:latest
```
### Deploy to Google Cloud Run
```bash
# Build and push to GCR
gcloud builds submit --tag gcr.io/PROJECT_ID/foldsite
gcloud run deploy --image gcr.io/PROJECT_ID/foldsite --platform managed
```
### Deploy to Azure Container Instances
```bash
# Create container instance
az container create \
--resource-group myResourceGroup \
--name foldsite \
--image myregistry.azurecr.io/foldsite:latest \
--ports 8081
```
## Next Steps
- **[Production Deployment](production.md)** - Production-grade setup
- **[Local Development](local-development.md)** - Development workflow
- **[Support](../support.md)** - Get help
Docker provides a solid foundation for deploying Foldsite anywhere. From development to production, containers ensure consistency and reliability.

View File

@ -0,0 +1,380 @@
---
version: "1.0"
date: "2025-01-15"
author: "DWS Foldsite Team"
title: "Deployment Overview"
description: "Getting Foldsite running - from local development to production"
summary: "Learn how to deploy Foldsite in various environments: local development, Docker containers, or production servers."
quick_tips:
- "Start with local development for fastest iteration"
- "Docker provides consistent environments across machines"
- "Production deployment supports both dynamic and static modes"
---
# Deployment Overview
Foldsite is flexible in how you run it. Choose the deployment method that fits your needs:
## Deployment Options
### [Local Development](local-development.md)
**Best for:** Content creation, theme development, testing
Run Foldsite directly with Python for the fastest development cycle. Changes to content and templates appear immediately (no rebuild needed).
```bash
python main.py --config config.toml
```
**Pros:**
- Fastest iteration - see changes instantly
- Easy debugging with Python stack traces
- Full access to logs and error messages
**Cons:**
- Requires Python environment
- Manual dependency management
- Not suitable for production
**When to use:** Always use this during development. It's the fastest way to see your changes.
### [Docker Deployment](docker.md)
**Best for:** Consistent environments, easy deployment, testing production builds
Run Foldsite in a Docker container for isolated, reproducible deployments.
```bash
docker-compose up
```
**Pros:**
- Consistent across development and production
- Isolated dependencies
- Easy to share with team members
- Simplifies deployment to cloud platforms
**Cons:**
- Slight overhead from containerization
- Requires Docker knowledge
- Extra layer to debug
**When to use:** Use Docker when you need consistency across environments, or when deploying to platforms that support containers.
### [Production Deployment](production.md)
**Best for:** Public-facing websites, high-traffic sites, static hosting
Deploy Foldsite as either a dynamic Python server or export to static files.
**Dynamic Mode:**
```bash
gunicorn -w 4 -b 0.0.0.0:8081 main:app
```
**Static Export:**
```bash
# Generate static HTML files
python export.py --output ./dist
```
**Pros:**
- Optimized for production workloads
- Can use static hosting (cheap/free)
- Supports CDN caching
- Professional-grade performance
**Cons:**
- More complex setup
- Requires understanding of web servers
- Static mode requires rebuilds for updates
**When to use:** Use this for your live website once development is complete.
## Quick Comparison
| Method | Speed | Complexity | Best For |
|--------|-------|------------|----------|
| **Local Development** | ⚡⚡⚡ | ⭐ | Creating content and themes |
| **Docker** | ⚡⚡ | ⭐⭐ | Team collaboration, staging |
| **Production (Dynamic)** | ⚡⚡ | ⭐⭐⭐ | Live sites with frequent updates |
| **Production (Static)** | ⚡⚡⚡ | ⭐⭐⭐ | Live sites, maximum performance |
## Prerequisites
### For All Deployment Methods
1. **Git** (to clone the repository)
```bash
git --version
```
2. **A text editor** (VS Code, Sublime, vim, etc.)
### For Local Development
1. **Python 3.10+**
```bash
python3 --version
```
2. **pip** (Python package manager)
```bash
pip --version
```
### For Docker Deployment
1. **Docker** and **Docker Compose**
```bash
docker --version
docker-compose --version
```
### For Production Deployment
Choose based on your hosting strategy:
- **Dynamic mode:** Python 3.10+, web server (nginx/apache)
- **Static mode:** Any web server or static host (GitHub Pages, Netlify, etc.)
## Getting the Source Code
All deployment methods start by getting Foldsite:
```bash
# Clone the repository
git clone https://github.com/DWSresearch/foldsite.git
cd foldsite
# Or download and extract the latest release
wget https://github.com/DWSresearch/foldsite/archive/main.zip
unzip main.zip
cd foldsite-main
```
## Configuration
Every deployment uses a `config.toml` file to specify paths and settings:
```toml
[paths]
content_dir = "/path/to/your/content"
templates_dir = "/path/to/your/templates"
styles_dir = "/path/to/your/styles"
[server]
listen_address = "0.0.0.0"
listen_port = 8081
admin_browser = false
admin_password = "change-me"
max_threads = 4
debug = false
access_log = true
```
**Important:** Adjust these paths before running Foldsite!
### Development Config Example
```toml
[paths]
content_dir = "./my-site/content"
templates_dir = "./my-site/templates"
styles_dir = "./my-site/styles"
[server]
listen_address = "127.0.0.1" # Local only
listen_port = 8081
debug = true # Enable debug mode
access_log = true
```
### Production Config Example
```toml
[paths]
content_dir = "/var/www/site/content"
templates_dir = "/var/www/site/templates"
styles_dir = "/var/www/site/styles"
[server]
listen_address = "0.0.0.0" # All interfaces
listen_port = 8081
debug = false # Disable debug mode
access_log = true
max_threads = 8 # More workers for production
```
## Typical Deployment Workflow
### 1. Development Phase
Use **local development** for content creation and theme building:
```bash
# Edit content
vim content/my-post.md
# Run server
python main.py --config config.toml
# Visit http://localhost:8081
# See changes immediately
```
### 2. Testing Phase
Use **Docker** to test in a production-like environment:
```bash
# Build and run
docker-compose up
# Test on http://localhost:8081
# Verify everything works in container
```
### 3. Deployment Phase
Deploy to **production** using your preferred method:
```bash
# Option A: Dynamic server
gunicorn -w 4 main:app
# Option B: Static export
python export.py --output ./dist
rsync -avz ./dist/ user@server:/var/www/site/
```
## Common Scenarios
### Scenario: Personal Blog
**Best deployment:** Local development + static export to GitHub Pages
```bash
# Develop locally
python main.py --config config.toml
# Export to static files
python export.py --output ./docs
# Push to GitHub (Pages serves from /docs)
git add docs/
git commit -m "Update site"
git push
```
### Scenario: Team Documentation
**Best deployment:** Docker for everyone, dynamic server in production
```bash
# Everyone on the team uses Docker
docker-compose up
# Production uses dynamic Python server
# for real-time updates when docs change
```
### Scenario: Photography Portfolio
**Best deployment:** Local development, Docker for staging, static export for production
High-performance static site with CDN for fast image delivery.
## Troubleshooting
### Port Already in Use
```
OSError: [Errno 48] Address already in use
```
**Solution:** Change `listen_port` in config.toml or stop the other service using that port.
### Module Not Found
```
ModuleNotFoundError: No module named 'flask'
```
**Solution:** Install dependencies:
```bash
pip install -r requirements.txt
```
### Permission Denied
```
PermissionError: [Errno 13] Permission denied
```
**Solution:** Check directory permissions:
```bash
chmod -R 755 content/ templates/ styles/
```
### Template Not Found
```
Exception: Base template not found
```
**Solution:** Ensure `base.html` exists in templates directory:
```bash
ls templates/base.html
```
## Next Steps
Choose your deployment path:
- **[Local Development Guide](deployment/local-development.md)** - Start here for development
- **[Docker Deployment Guide](deployment/docker.md)** - Containerized deployment
- **[Production Deployment Guide](deployment/production.md)** - Go live with your site
## Security Considerations
### Development
- **Only bind to localhost** (`listen_address = "127.0.0.1"`)
- **Never commit config.toml** with sensitive data to version control
### Production
- **Use HTTPS** - Always use TLS/SSL in production
- **Strong passwords** - If using admin interface, use strong passwords
- **Firewall rules** - Only expose necessary ports
- **Regular updates** - Keep Foldsite and dependencies updated
- **Content validation** - Be careful with user-uploaded content
See [Production Deployment](production.md) for detailed security guidance.
## Performance Tips
### For All Deployments
- **Use hidden files** for drafts (`___draft.md`) to avoid processing
- **Optimize images** before uploading (Foldsite generates thumbnails, but smaller source = faster)
- **Minimize template complexity** - Simple templates render faster
### For Production
- **Enable caching** at the web server level
- **Use a CDN** for static assets
- **Compress responses** with gzip/brotli
- **Monitor resource usage** and scale as needed
## Getting Help
Need assistance with deployment?
- **[Support](../support.md)** - Community help and resources
- **GitHub Issues** - Report bugs or ask questions
- **Example Configs** - See `/examples` directory in repository
Happy deploying!

View File

@ -0,0 +1,629 @@
---
version: "1.0"
date: "2025-01-15"
author: "DWS Foldsite Team"
title: "Local Development"
description: "Running Foldsite on your local machine for development"
summary: "Complete guide to setting up and running Foldsite locally for the fastest development workflow."
quick_tips:
- "Local development gives instant feedback - no build step needed"
- "Use debug mode to see template discovery and errors clearly"
- "Changes to content and templates appear immediately on refresh"
---
# Local Development
Running Foldsite locally is the fastest way to develop your site. Changes to content and templates appear instantly without any build process.
## Prerequisites
### Required Software
**Python 3.10 or higher**
```bash
# Check your Python version
python3 --version
# Should output: Python 3.10.x or higher
```
If you don't have Python 3.10+:
- **macOS:** `brew install python3`
- **Ubuntu/Debian:** `sudo apt install python3.10`
- **Windows:** Download from [python.org](https://www.python.org/downloads/)
**pip (Python package manager)**
```bash
# Check pip version
pip --version
# If missing, install
python3 -m ensurepip --upgrade
```
**Git (recommended)**
```bash
git --version
```
### Optional but Recommended
**Virtual environment support**
```bash
python3 -m venv --help
```
**Text editor with syntax highlighting**
- VS Code (recommended)
- Sublime Text
- Vim/Neovim
- Any editor you prefer
## Installation
### Step 1: Get Foldsite
**Option A: Clone with Git (recommended)**
```bash
# Clone the repository
git clone https://github.com/DWSresearch/foldsite.git
cd foldsite
```
**Option B: Download ZIP**
```bash
# Download latest release
wget https://github.com/DWSresearch/foldsite/archive/main.zip
unzip main.zip
cd foldsite-main
```
### Step 2: Create Virtual Environment
Using a virtual environment keeps dependencies isolated:
```bash
# Create virtual environment
python3 -m venv venv
# Activate it
# On macOS/Linux:
source venv/bin/activate
# On Windows:
venv\Scripts\activate
# Your prompt should now show (venv)
```
**Why virtual environment?**
- Isolates project dependencies
- Prevents conflicts with system Python
- Easy to recreate or remove
- Professional Python practice
### Step 3: Install Dependencies
```bash
# Ensure pip is up to date
pip install --upgrade pip
# Install Foldsite dependencies
pip install -r requirements.txt
```
**Dependencies installed:**
- Flask - Web framework
- Jinja2 - Template engine
- mistune - Markdown parser
- python-frontmatter - YAML frontmatter parsing
- Pillow - Image processing
- Gunicorn - WSGI server
**Troubleshooting:**
If you see compilation errors:
```bash
# Install build tools
# macOS:
xcode-select --install
# Ubuntu/Debian:
sudo apt install python3-dev build-essential
# Then retry:
pip install -r requirements.txt
```
### Step 4: Set Up Your Content
Create your site directory structure:
```bash
# Create your site directories
mkdir -p my-site/content
mkdir -p my-site/templates
mkdir -p my-site/styles
# Create a basic index page
echo "# Welcome to My Site" > my-site/content/index.md
# Copy example templates to start
cp -r example_site/template/* my-site/templates/
cp -r example_site/style/* my-site/styles/
```
### Step 5: Configure Foldsite
Create a configuration file:
```bash
# Copy example config
cp config.toml my-site-config.toml
```
Edit `my-site-config.toml`:
```toml
[paths]
content_dir = "/absolute/path/to/my-site/content"
templates_dir = "/absolute/path/to/my-site/templates"
styles_dir = "/absolute/path/to/my-site/styles"
[server]
listen_address = "127.0.0.1" # Only accessible from your machine
listen_port = 8081
admin_browser = false # Disable admin interface for now
max_threads = 4
debug = true # Enable debug mode for development
access_log = true
```
**Important:** Use absolute paths in development to avoid confusion.
**Find absolute path:**
```bash
# macOS/Linux:
cd my-site && pwd
# Windows:
cd my-site && cd
```
## Running Foldsite
### Start the Server
```bash
# Make sure virtual environment is activated
source venv/bin/activate # or venv\Scripts\activate on Windows
# Run Foldsite
python main.py --config my-site-config.toml
```
**Expected output:**
```
[2025-01-15 10:30:45] [INFO] Starting Foldsite server
[2025-01-15 10:30:45] [INFO] Content directory: /path/to/my-site/content
[2025-01-15 10:30:45] [INFO] Templates directory: /path/to/my-site/templates
[2025-01-15 10:30:45] [INFO] Listening on http://127.0.0.1:8081
```
### Visit Your Site
Open your browser to:
```
http://localhost:8081
```
You should see your site!
### Stop the Server
Press `Ctrl+C` in the terminal where Foldsite is running.
## Development Workflow
### The Edit-Refresh Cycle
Foldsite has **no build step**. Changes appear immediately:
1. **Edit content** - Modify markdown files
2. **Save file** - Ctrl+S / Cmd+S
3. **Refresh browser** - F5 or Cmd+R
4. **See changes instantly**
**What updates live:**
- Content (markdown files)
- Templates (HTML files)
- Styles (CSS files)
- Configuration (requires restart)
### Example Workflow
**Scenario:** Adding a blog post
```bash
# 1. Create new post
vim my-site/content/blog/my-new-post.md
```
```markdown
---
title: "My New Blog Post"
date: "2025-01-15"
tags: ["tutorial", "foldsite"]
---
# My New Blog Post
This is my latest post!
```
```bash
# 2. Save file and switch to browser
# 3. Visit http://localhost:8081/blog/my-new-post.md
# 4. See your post rendered immediately
```
**No restart needed!**
### Working with Templates
```bash
# 1. Edit template
vim my-site/templates/__file.md.html
```
```html
<!-- Add a new section -->
<article>
<header>
<h1>{{ metadata.title }}</h1>
<time>{{ metadata.date }}</time>
</header>
{{ content|safe }}
<!-- NEW: Add related posts -->
{% set related = get_related_posts(currentPath, limit=3) %}
{% if related %}
<aside class="related">
<h3>Related Posts</h3>
{% for post in related %}
<a href="{{ post.url }}">{{ post.title }}</a>
{% endfor %}
</aside>
{% endif %}
</article>
```
```bash
# 2. Save and refresh browser
# 3. See related posts section appear
```
### Working with Styles
```bash
# 1. Edit CSS
vim my-site/styles/base.css
```
```css
/* Add new styles */
.related {
margin-top: 2rem;
padding: 1rem;
background: #f5f5f5;
border-radius: 4px;
}
.related h3 {
margin-bottom: 0.5rem;
}
```
```bash
# 2. Save and hard refresh (Cmd+Shift+R / Ctrl+Shift+R)
# 3. See styled related posts
```
## Debug Mode
Enable debug mode for helpful development information:
```toml
[server]
debug = true
```
**What debug mode shows:**
- Template discovery process
- Which templates were considered
- Which template was chosen
- Detailed error messages with stack traces
- Template variables and context
**Example debug output:**
When visiting a page, console shows:
```
[DEBUG] Template search for: blog/my-post.md
[DEBUG] Checking: templates/blog/my-post.html - Not found
[DEBUG] Checking: templates/blog/__file.md.html - Found!
[DEBUG] Using template: templates/blog/__file.md.html
[DEBUG] Available variables: content, metadata, currentPath, styles
```
**View in browser:**
With debug mode, error pages show:
- Full Python stack trace
- Template rendering context
- What went wrong and where
- Suggestions for fixes
## Common Development Tasks
### Creating New Pages
```bash
# Simple page
echo "# About Me\n\nI'm a web developer." > my-site/content/about.md
# With frontmatter
cat > my-site/content/projects.md << 'EOF'
---
title: "My Projects"
description: "Things I've built"
---
# My Projects
Here are some things I've worked on...
EOF
```
### Organizing Content
```bash
# Create a blog section
mkdir -p my-site/content/blog
# Add posts
for i in {1..5}; do
cat > my-site/content/blog/post-$i.md << EOF
---
title: "Blog Post $i"
date: "2024-01-$i"
tags: ["example"]
---
# Post $i
Content here...
EOF
done
```
### Testing Template Helpers
Create a test page to experiment:
```bash
cat > my-site/content/test.md << 'EOF'
---
title: "Template Helper Test"
---
# Testing Helpers
## Recent Posts
{% for post in get_recent_posts(limit=5) %}
- [{{ post.title }}]({{ post.url }}) - {{ post.date }}
{% endfor %}
## All Tags
{% for tag in get_all_tags() %}
- {{ tag.name }} ({{ tag.count }})
{% endfor %}
## Current Path Info
- Path: {{ currentPath }}
- Metadata: {{ metadata }}
EOF
```
Visit `/test.md` to see helper output.
### Hiding Work in Progress
Use the `___` prefix:
```bash
# Hidden draft
vim my-site/content/___draft-post.md
# Hidden development folder
mkdir my-site/content/___testing
```
These won't appear in navigation or listings.
## Editor Setup
### VS Code
Recommended extensions:
- **Python** (Microsoft)
- **Jinja** (wholroyd.jinja)
- **Markdown All in One** (yzhang.markdown-all-in-one)
**Settings:**
```json
{
"files.associations": {
"*.html": "jinja-html"
},
"editor.formatOnSave": true
}
```
### Vim/Neovim
Add to `.vimrc` or `init.vim`:
```vim
" Jinja syntax for .html files
autocmd BufNewFile,BufRead */templates/*.html set filetype=jinja
" Markdown settings
autocmd FileType markdown setlocal spell spelllang=en_us
autocmd FileType markdown setlocal textwidth=80
```
## Troubleshooting
### Port Already in Use
```
Error: [Errno 48] Address already in use
```
**Solution 1:** Change port in config:
```toml
[server]
listen_port = 8082
```
**Solution 2:** Find and kill process:
```bash
# Find process using port 8081
lsof -i :8081
# Kill it
kill -9 <PID>
```
### Module Not Found
```
ModuleNotFoundError: No module named 'flask'
```
**Solution:**
```bash
# Ensure virtual environment is activated
source venv/bin/activate
# Reinstall dependencies
pip install -r requirements.txt
```
### Template Not Found
```
Exception: Base template not found
```
**Solution:**
```bash
# Check templates directory exists and has base.html
ls my-site/templates/base.html
# If missing, copy from example
cp example_site/template/base.html my-site/templates/
```
### Changes Not Appearing
**Possible causes:**
1. **Browser cache** - Hard refresh (Cmd/Ctrl + Shift + R)
2. **Wrong file** - Check you're editing the file Foldsite is using
3. **Configuration issue** - Verify config.toml paths
4. **Syntax error** - Check console for error messages
**Debug:**
```bash
# Enable debug mode
# Edit config.toml
[server]
debug = true
# Restart Foldsite
# Check console output
```
### Permission Denied
```
PermissionError: [Errno 13] Permission denied
```
**Solution:**
```bash
# Fix permissions
chmod -R 755 my-site/
# Or run with correct user
sudo chown -R $USER:$USER my-site/
```
## Performance Tips
### Development Speed
**Fast iteration:**
- Keep browser DevTools open
- Use multiple browser windows for comparison
- Enable auto-reload browser extensions
- Use terminal multiplexer (tmux/screen)
**Organize workspace:**
```
Terminal 1: Foldsite server
Terminal 2: Content editing
Terminal 3: Git operations
Browser: Live preview
Editor: Code/templates
```
### Working with Large Sites
If your site has many files:
```toml
[server]
max_threads = 8 # Increase workers
```
**Cache considerations:**
- Template helpers are cached automatically
- Folder contents cached for 5 minutes
- Recent posts cached for 10 minutes
- Restart server to clear caches
## Next Steps
Now that you have local development running:
- **[Templates Guide](../templates/)** - Learn the template system
- **[Template Helpers](../templates/template-helpers.md)** - Explore helper functions
- **[Recipes](../recipes/)** - Copy working examples
- **[Docker Deployment](docker.md)** - Test in container
- **[Production Deployment](production.md)** - Go live
## Tips from Developers
> "Keep the server running in a dedicated terminal. Switch to it to see errors immediately." — Foldsite contributor
> "Use `___testing/` folder for experimenting. It's ignored so you can mess around without affecting the site." — Content creator
> "Debug mode is your friend. Always enable it in development." — Theme developer
> "Create test pages to try helper functions. Much faster than reading docs." — Documentation writer
Happy developing! Local development is where the magic happens. 🚀

View File

@ -0,0 +1,810 @@
---
version: "1.0"
date: "2025-01-15"
author: "DWS Foldsite Team"
title: "Production Deployment"
description: "Deploying Foldsite for production use"
summary: "Complete guide to deploying Foldsite in production - from VPS servers to static hosting, with security, performance, and reliability best practices."
quick_tips:
- "Use Gunicorn with multiple workers for dynamic deployments"
- "Static export is fastest and cheapest for sites that don't change frequently"
- "Always use HTTPS in production with proper SSL certificates"
---
# Production Deployment
Deploy Foldsite to serve real traffic with reliability, security, and performance.
## Deployment Options
### Option 1: Dynamic Server (Python)
**Best for:**
- Frequently updated content
- Sites needing template helpers in real-time
- Admin file browser interface
- Dynamic content generation
**Characteristics:**
- Runs Python/Gunicorn server
- Content updates appear immediately
- Template helpers work dynamically
- Requires server with Python
**Hosting:** VPS, dedicated server, PaaS platforms
### Option 2: Static Export
**Best for:**
- Infrequently updated sites
- Maximum performance
- Minimal cost
- CDN delivery
**Characteristics:**
- Pre-rendered HTML files
- Blazing fast delivery
- Can host anywhere (GitHub Pages, Netlify, S3)
- Rebuild required for updates
**Hosting:** Static hosts, CDN, object storage
## Dynamic Server Deployment
### Prerequisites
- Linux server (Ubuntu 20.04+ recommended)
- Python 3.10+
- Domain name
- SSH access
### Step 1: Server Setup
**Update system:**
```bash
sudo apt update
sudo apt upgrade -y
```
**Install dependencies:**
```bash
# Python and pip
sudo apt install -y python3.10 python3-pip python3-venv
# Build tools
sudo apt install -y build-essential python3-dev
# Nginx
sudo apt install -y nginx
# Certbot for SSL
sudo apt install -y certbot python3-certbot-nginx
```
### Step 2: Deploy Foldsite
**Create user:**
```bash
sudo useradd -m -s /bin/bash foldsite
sudo su - foldsite
```
**Clone and setup:**
```bash
# Clone repository
git clone https://github.com/DWSresearch/foldsite.git
cd foldsite
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
pip install gunicorn # Production WSGI server
```
**Setup your content:**
```bash
# Create site structure
mkdir -p ~/site/content
mkdir -p ~/site/templates
mkdir -p ~/site/styles
# Copy your content
# (upload via SCP, rsync, or git)
```
**Create production config:**
```bash
vim ~/foldsite/production-config.toml
```
```toml
[paths]
content_dir = "/home/foldsite/site/content"
templates_dir = "/home/foldsite/site/templates"
styles_dir = "/home/foldsite/site/styles"
[server]
listen_address = "127.0.0.1" # Only accept local connections
listen_port = 8081
admin_browser = false # Disable for security
max_threads = 8 # Adjust based on server
debug = false # Never enable in production
access_log = true
```
### Step 3: Systemd Service
Create service file:
```bash
sudo vim /etc/systemd/system/foldsite.service
```
```ini
[Unit]
Description=Foldsite Web Server
After=network.target
[Service]
Type=simple
User=foldsite
Group=foldsite
WorkingDirectory=/home/foldsite/foldsite
Environment="PATH=/home/foldsite/foldsite/venv/bin"
ExecStart=/home/foldsite/foldsite/venv/bin/gunicorn \
--workers 4 \
--bind 127.0.0.1:8081 \
--access-logfile /var/log/foldsite/access.log \
--error-logfile /var/log/foldsite/error.log \
--config /home/foldsite/foldsite/production-config.toml \
main:app
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
**Create log directory:**
```bash
sudo mkdir -p /var/log/foldsite
sudo chown foldsite:foldsite /var/log/foldsite
```
**Enable and start service:**
```bash
sudo systemctl daemon-reload
sudo systemctl enable foldsite
sudo systemctl start foldsite
# Check status
sudo systemctl status foldsite
```
### Step 4: Nginx Reverse Proxy
**Create Nginx config:**
```bash
sudo vim /etc/nginx/sites-available/foldsite
```
```nginx
upstream foldsite {
server 127.0.0.1:8081;
keepalive 32;
}
server {
listen 80;
server_name your-domain.com www.your-domain.com;
# Security headers
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 "no-referrer-when-downgrade" always;
# Logs
access_log /var/log/nginx/foldsite-access.log;
error_log /var/log/nginx/foldsite-error.log;
# Max upload size
client_max_body_size 10M;
# Proxy to Foldsite
location / {
proxy_pass http://foldsite;
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Cache static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://foldsite;
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Security: deny access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
```
**Enable site:**
```bash
sudo ln -s /etc/nginx/sites-available/foldsite /etc/nginx/sites-enabled/
sudo nginx -t # Test configuration
sudo systemctl reload nginx
```
### Step 5: SSL Certificate
**Get certificate with Certbot:**
```bash
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
```
Follow prompts. Certbot will:
- Obtain certificate from Let's Encrypt
- Modify Nginx config for HTTPS
- Setup auto-renewal
**Verify auto-renewal:**
```bash
sudo certbot renew --dry-run
```
**Final Nginx config (with SSL):**
Certbot updates your config to include:
```nginx
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ... rest of config
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name your-domain.com www.your-domain.com;
return 301 https://$server_name$request_uri;
}
```
### Step 6: Firewall
**Configure UFW:**
```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
```
### Verification
Visit your domain:
```
https://your-domain.com
```
Should see your Foldsite with valid SSL!
## Static Export Deployment
### Generate Static Files
*Note: Static export functionality may need to be implemented or use a static site generator mode*
**Conceptual approach:**
```python
# export.py
import os
from pathlib import Path
from src.rendering.renderer import render_page
from src.config.config import Configuration
def export_static(config_path, output_dir):
"""Export all pages to static HTML"""
config = Configuration(config_path)
config.load_config()
output = Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
# Walk content directory
for content_file in config.content_dir.rglob('*'):
if content_file.is_file() and not content_file.name.startswith('___'):
# Generate output path
rel_path = content_file.relative_to(config.content_dir)
out_path = output / rel_path.with_suffix('.html')
out_path.parent.mkdir(parents=True, exist_ok=True)
# Render and save
html = render_page(
content_file,
base_path=config.content_dir,
template_path=config.templates_dir,
style_path=config.styles_dir
)
with open(out_path, 'w') as f:
f.write(html)
# Copy styles
import shutil
shutil.copytree(config.styles_dir, output / 'styles')
if __name__ == '__main__':
import sys
export_static(sys.argv[1], sys.argv[2])
```
**Usage:**
```bash
python export.py config.toml ./dist
```
### Deploy Static Files
#### GitHub Pages
```bash
# Export to docs/
python export.py config.toml ./docs
# Commit and push
git add docs/
git commit -m "Update site"
git push
# Enable Pages in GitHub repo settings
# Source: docs/ folder
```
#### Netlify
```bash
# Export
python export.py config.toml ./dist
# Install Netlify CLI
npm install -g netlify-cli
# Deploy
netlify deploy --prod --dir=dist
```
**Or use continuous deployment:**
```yaml
# netlify.toml
[build]
command = "pip install -r requirements.txt && python export.py config.toml dist"
publish = "dist"
```
#### AWS S3 + CloudFront
```bash
# Export
python export.py config.toml ./dist
# Sync to S3
aws s3 sync ./dist s3://your-bucket-name --delete
# Invalidate CloudFront cache
aws cloudfront create-invalidation --distribution-id YOUR_DIST_ID --paths "/*"
```
#### Vercel
```bash
# Export
python export.py config.toml ./dist
# Deploy
vercel --prod ./dist
```
## Performance Optimization
### Nginx Caching
Add to Nginx config:
```nginx
# Define cache path
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=foldsite_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache foldsite_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://foldsite;
}
}
```
### Gzip Compression
```nginx
# In /etc/nginx/nginx.conf
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json;
```
### Image Optimization
Foldsite automatically generates thumbnails, but optimize source images:
```bash
# Install optimization tools
sudo apt install jpegoptim optipng
# Optimize JPEGs
find content/ -name "*.jpg" -exec jpegoptim --strip-all {} \;
# Optimize PNGs
find content/ -name "*.png" -exec optipng -o2 {} \;
```
### CDN Integration
Use CDN for static assets:
```nginx
# Separate static assets
location /styles/ {
alias /home/foldsite/site/styles/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location /download/ {
# Proxy to Foldsite for thumbnails
proxy_pass http://foldsite;
expires 30d;
}
```
Then point DNS for `static.yourdomain.com` to CDN origin.
## Monitoring & Logging
### Application Logs
**View logs:**
```bash
# Systemd logs
sudo journalctl -u foldsite -f
# Application logs
tail -f /var/log/foldsite/error.log
tail -f /var/log/foldsite/access.log
```
### Nginx Logs
```bash
tail -f /var/log/nginx/foldsite-access.log
tail -f /var/log/nginx/foldsite-error.log
```
### Log Rotation
Create `/etc/logrotate.d/foldsite`:
```
/var/log/foldsite/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 foldsite foldsite
sharedscripts
postrotate
systemctl reload foldsite
endscript
}
```
### Monitoring Tools
**Install basic monitoring:**
```bash
# Netdata (system monitoring)
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
# Access at http://your-server:19999
```
**Check application health:**
```bash
#!/bin/bash
# health-check.sh
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8081/)
if [ $response -eq 200 ]; then
echo "Foldsite is healthy"
exit 0
else
echo "Foldsite is down (HTTP $response)"
systemctl restart foldsite
exit 1
fi
```
Run via cron:
```bash
*/5 * * * * /usr/local/bin/health-check.sh >> /var/log/foldsite/health.log 2>&1
```
## Backup Strategy
### Content Backup
```bash
#!/bin/bash
# backup.sh
BACKUP_DIR="/backups/foldsite"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Backup content, templates, styles
tar czf $BACKUP_DIR/site-$DATE.tar.gz \
/home/foldsite/site/
# Keep only last 30 days
find $BACKUP_DIR -name "site-*.tar.gz" -mtime +30 -delete
echo "Backup completed: site-$DATE.tar.gz"
```
**Run daily via cron:**
```bash
0 2 * * * /usr/local/bin/backup.sh
```
### Remote Backup
```bash
# Sync to remote server
rsync -avz /home/foldsite/site/ user@backup-server:/backups/foldsite/
# Or sync to S3
aws s3 sync /home/foldsite/site/ s3://your-backup-bucket/foldsite/
```
## Updating Foldsite
### Update Process
```bash
# As foldsite user
cd ~/foldsite
# Pull latest code
git pull
# Activate venv
source venv/bin/activate
# Update dependencies
pip install -r requirements.txt
# Restart service
sudo systemctl restart foldsite
# Check logs
sudo journalctl -u foldsite -n 50
```
### Zero-Downtime Updates
Use multiple Gunicorn workers and graceful reloading:
```bash
# Graceful reload (workers restart one by one)
sudo systemctl reload foldsite
# Or send HUP signal to Gunicorn
sudo pkill -HUP gunicorn
```
## Security Hardening
### Disable Directory Listing
Nginx automatically prevents this, but verify:
```nginx
autoindex off;
```
### Rate Limiting
Add to Nginx config:
```nginx
limit_req_zone $binary_remote_addr zone=foldsite_limit:10m rate=10r/s;
server {
location / {
limit_req zone=foldsite_limit burst=20 nodelay;
# ... rest of config
}
}
```
### Fail2ban
Protect against brute force:
```bash
sudo apt install fail2ban
# Create /etc/fail2ban/jail.local
[nginx-foldsite]
enabled = true
port = http,https
filter = nginx-foldsite
logpath = /var/log/nginx/foldsite-access.log
maxretry = 5
bantime = 3600
```
### Security Headers
Already in Nginx config, but verify:
```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 "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:;" always;
```
### File Permissions
Ensure proper permissions:
```bash
# Content should be readable by foldsite user
chmod -R 755 ~/site/content
chmod -R 755 ~/site/templates
chmod -R 755 ~/site/styles
# Application should not be writable
chmod -R 555 ~/foldsite/src
```
## Troubleshooting
### Service Won't Start
```bash
# Check logs
sudo journalctl -u foldsite -xe
# Common issues:
# - Wrong Python path
# - Missing dependencies
# - Port already in use
# - Permission errors
```
### 502 Bad Gateway
Nginx can't reach Foldsite:
```bash
# Check if Foldsite is running
sudo systemctl status foldsite
# Check if port is listening
sudo netstat -tulpn | grep 8081
# Check Nginx error log
sudo tail /var/log/nginx/error.log
```
### High Memory Usage
```bash
# Check process memory
ps aux | grep gunicorn
# Reduce workers or add swap
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```
### Slow Response Times
```bash
# Check Nginx access logs for slow requests
sudo tail -f /var/log/nginx/foldsite-access.log
# Enable query logging in Foldsite
# Check for expensive template helpers
# Consider caching with Redis/Memcached
```
## Platform-Specific Guides
### DigitalOcean
```bash
# Create droplet (Ubuntu 22.04)
# Follow server setup steps above
# Use DigitalOcean firewall for security
# Enable backups in control panel
```
### AWS EC2
```bash
# Launch Ubuntu instance
# Setup security groups (ports 22, 80, 443)
# Use Elastic IP for static IP
# Consider RDS for database if needed
```
### Hetzner Cloud
```bash
# Create CX11 or larger instance
# Follow server setup
# Use Hetzner firewall
# Consider Hetzner volumes for storage
```
## Next Steps
- **[Local Development](local-development.md)** - Development workflow
- **[Docker Deployment](docker.md)** - Container deployment
- **[Support](../support.md)** - Get help
Your Foldsite is now production-ready! Monitor it regularly, keep it updated, and enjoy your self-hosted corner of the internet.