Skip to content

Latest commit

 

History

History
333 lines (226 loc) · 7.27 KB

File metadata and controls

333 lines (226 loc) · 7.27 KB

Advanced Topics

Hooks

Execute shell commands on specific events. Configure globally in YAML.

hooks:
  shell: /bin/bash

  hourly:
    - echo "Hourly task"

  prestart:
    - echo "Starting GoBlog"

  postpost:
    - echo "New post at {{.URL}}"

  postupdate:
    - echo "Updated {{.URL}}"

  postdelete:
    - echo "Deleted {{.URL}}"

  postundelete:
    - echo "Undeleted {{.URL}}"

Post hooks receive template variables:

  • .URL (string): The post's URL
  • .Post (object): The post object with all post data

Use hooks for tasks like:

  • Sending notifications to external services
  • Triggering static site generators
  • Backing up posts after changes
  • Updating search indexes

Regex Redirects

Create custom redirects using regular expressions:

pathRedirects:
  - from: "\\/index\\.xml"
    to: ".rss"
    type: 302

  - from: "^\\/(old|legacy)\\/(.*)$"
    to: "/new/$2"
    type: 301

The from field is a Go regular expression. The to field can use capture groups ($1, $2, etc.). The type field is optional (defaults to 302).

Post Aliases

Redirect old URLs to new posts using the aliases front matter parameter:

---
path: /new-path
aliases:
  - /old-path
  - /another-old-path
---

Old URLs redirect permanently (301) to the new post.

Custom Domains

Short Domain

Use a custom short domain for compact post URLs:

server:
  shortPublicAddress: https://short.example.com

Every post gets a short URL at /s/{hex-id} which redirects to the full post path.

Media Domain

Use a custom domain for serving media files:

server:
  mediaAddress: https://media.example.com
  cspDomains:
    - media.example.com  # Add to Content Security Policy

Custom domains (short URLs and media URLs) are global for the entire GoBlog instance. You cannot use different domains for different blogs on the same instance.

Multiple Blogs

Run multiple blogs under one GoBlog installation. Common use cases:

  • Multiple languages: Separate blogs for different languages
  • Different content types: Personal vs. professional content

Example configuration:

defaultBlog: en

blogs:
  en:
    path: /
    lang: en
    # title and description are configured via the settings UI

  de:
    path: /de
    lang: de

  fr:
    path: /fr
    lang: fr

Each blog has its own:

  • Title and description (configurable via settings UI)
  • Sections and taxonomies
  • Menus and navigation
  • Settings and preferences
  • ActivityPub actor (@blogname@yourdomain.com)

All blogs share the same user account and global settings (server, database, etc.).

Performance Tuning

Enable Caching

Response caching is enabled by default with a 6-hour TTL. Configure in YAML (see example-config.yml for options):

cache:
  enable: true
  expiration: 600  # Per-route override in seconds

Append ?cache=0 or ?cache=false to any URL to skip the cache for that request.

Optimize Database

Run SQLite maintenance commands:

sqlite3 data/db.sqlite "VACUUM;"
sqlite3 data/db.sqlite "ANALYZE;"

Use CDN for Media

Configure external media storage (BunnyCDN, FTP) to offload media serving. See example-config.yml for configuration.

Database Backup

Automatic SQL Dump

Enable hourly SQL dumps:

database:
  dumpFile: data/db.sql

Manual Backup

Stop GoBlog, copy the data directory, restart:

# Docker
docker-compose down
cp -r data data-backup-$(date +%Y%m%d)
docker-compose up -d

# Binary
# Stop GoBlog, then:
cp -r data data-backup-$(date +%Y%m%d)
# Restart GoBlog

Tor Hidden Service

GoBlog can serve as a Tor .onion hidden service. Set server.tor: true in your YAML config. Tor must be installed and available in $PATH.

When enabled, GoBlog:

  • Generates and persists an Ed25519 private key at data/tor/onion.pk (the .onion address is stable across restarts)
  • Starts an onion service on port 80
  • Adds an Onion-Location HTTP header to all responses, directing Tor browsers to the .onion address
  • Logs the .onion address at startup

The .onion address is derived from the persistent key, so it remains the same across restarts. The cache is purged when Tor starts.

Docker Images

Two Docker images are available:

  • ghcr.io/jlelse/goblog:latest - Base image
  • ghcr.io/jlelse/goblog:tools - Includes sqlite3, bash, curl and other tools for hook commands or advanced users

Troubleshooting

Health Check Endpoint

GoBlog serves a /ping endpoint that returns HTTP 200 when the server is running. Use this for external monitoring, load balancers, or container health checks.

# CLI health check
./GoBlog --config ./config/config.yml healthcheck

# Manual check
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/ping

Common Issues

Posts not publishing

  • Check status: published in front matter
  • Check visibility: public (or unlisted)
  • For scheduled posts, ensure published date is in the past

ActivityPub not working

  • Ensure activityPub.enabled: true
  • Ensure privateMode.enabled: false
  • Verify DNS resolves to your server
  • Verify HTTPS is working properly

Media uploads failing

  • Check available disk space
  • Check file permissions on data/media/
  • For external storage, verify credentials

Logs

Application logs:

# Docker
docker-compose logs -f goblog

# Binary
./GoBlog --config ./config/config.yml

Access logs:

server:
  logging: true
  logFile: data/access.log

Debug mode:

debug: true

Database debug:

database:
  debug: true  # Log all SQL queries

Security

Private Mode

Restrict all public access. When enabled, every page requires authentication and X-Robots-Tag: noindex is set on all responses:

privateMode:
  enabled: true

Security Headers

When securityHeaders: true (auto-enabled with HTTPS), GoBlog sets: Strict-Transport-Security (1 year), Referrer-Policy: no-referrer, X-Content-Type-Options: nosniff, and a Content Security Policy. The CSP includes frame-ancestors 'none' (blocks all framing). See configuration.md for CSP domain configuration.

Cookies are set as Secure when security headers are enabled or the public address uses HTTPS. A 100 MB body size limit is enforced on all requests.

Access Logs

Enable HTTP access logging:

server:
  logging: true
  logFile: data/access.log

Access logs are rotated daily and include timestamp, method, path, status code, and response time, but do not log client IP addresses for privacy reasons.

Debug Logging

Enable verbose logging:

debug: true

Enable SQL query logging:

database:
  debug: true  # Log all SQL queries

Profiling (pprof)

Enable Go's built-in profiling endpoints for performance analysis:

pprof:
  enabled: true
  address: localhost:6060  # Optional, defaults to random port on localhost

When enabled, GoBlog starts a separate HTTP server with pprof endpoints:

  • /debug/pprof/ - Profiling index page
  • /debug/pprof/profile - CPU profile (30-second sample)

The pprof server runs on a separate listener (not the main server) and is opt-in only. For CLI-based profiling, use the --cpuprofile and --memprofile flags.