Captain is an experimental no-installation blog engine written by AI agents.
- No-installation required, single binary distribution
- SQLite database for simple deployment
- Markdown and HTML content support
- Customizable themes
- S3-compatible storage support
Captain is an experimental blog engine entirely mostly written by AI models. This project explores the possibilities and limitations of AI-generated software by creating a fully functional blogging platform.
Captain is written in Go and uses:
- Sqlite for data storage
- Fiber framework as a web server
- html/template for HTML templates
- Pull the Docker image:
docker pull ghcr.io/captain-corp/captain:latest
- Run the Docker container with default settings:
docker run --name captain -p 8080:8080 ghcr.io/captain-corp/captain:latest
- Access the admin interface at http://localhost:8080/setup
- Create a
docker-compose.yml
file with the following content:version: '3.8' services: captain: image: ghcr.io/captain-corp/captain:latest ports: - "8080:8080" volumes: - ./data:/data
- Run the Docker Compose setup:
docker-compose up -d
- Access the admin interface at http://localhost:8080/setup
For more details, refer to the Docker documentation.
- Download the latest release for your platform from the releases page
- Extract the archive:
unzip captain-<platform>.zip
- Move the binary to a location in your PATH:
sudo mv captain /usr/local/bin/
- Verify the installation:
captain
- Ensure you have Go 1.21 or later installed
- Clone the repository:
git clone https://github.com/captain-corp/captain.git cd captain
- Build and install:
make build sudo mv dist/captain /usr/local/bin/
When you first run Captain, if no user exists, you'll be guided through a setup wizard to create your first admin user. This ensures you can immediately access the admin interface to start writing.
-
Run Captain:
captain run
Available flags:
-b, --bind
: Address to bind to (overrides config)-p, --port
: Server port (overrides config)-i, --init-dev-db
: Initialize development database with test data-c, --config
: Config file path
Examples:
# Run with default settings captain run # Bind to all interfaces on port 3000 captain run -b 0.0.0.0 -p 3000 # Use custom config and initialize test data captain run -c /path/to/config.yaml -i
-
Follow the setup wizard prompts to create your admin account
-
Access the admin interface at http://localhost:8080/admin
-
Start writing!
make build
- Builds the binary in dist/captainmake run
- Builds and runs the servermake dev
- Runs the server in development mode with live reloadmake clean
- Removes build artifacts
make docker-build
- Builds Docker image tagged as captain:latestmake docker-run
- Runs the container and exposes port 8080
To use Docker:
Then open http://localhost:8080 in your browser
make test
- Runs all unit testsmake test-coverage
- Generates test coverage report in coverage.htmlmake lint
- Runs golangci-lint checksmake fmt
- Formats Go code
make create-user
- Creates a new user interactivelymake update-password
- Updates user password
Captain supports both local filesystem and S3-compatible storage for media files. You can configure the storage provider in your config.yaml
file.
Local storage is the default option. Files are stored in the local filesystem.
storage:
provider: "local"
local_path: "./uploads" # Path where files will be stored
To use S3 or an S3-compatible storage service (like MinIO, DigitalOcean Spaces, etc.):
- Configure your S3 credentials in
config.yaml
:
storage:
provider: "s3"
s3:
bucket: "your-bucket-name"
region: "your-region" # e.g., us-east-1
endpoint: "" # Optional: Custom endpoint for S3-compatible services
access_key: "your-key" # AWS access key
secret_key: "your-secret" # AWS secret key
-
Make sure your S3 bucket has the appropriate permissions:
- The provided AWS credentials should have permissions for:
s3:PutObject
- For uploading filess3:GetObject
- For retrieving filess3:DeleteObject
- For deleting files
- If using public access, configure the bucket policy to allow public read access
- The provided AWS credentials should have permissions for:
-
For S3-compatible services:
- Set the
endpoint
field to your service's endpoint URL - Make sure the
region
matches your service's configuration
- Set the
For development, you can use the run_dev
command which enables debug mode:
make run_dev
This will:
- Enable Gin's debug mode with detailed request logging
- Set GORM's log level to info for detailed SQL logging
- Display more detailed error messages
You can also:
- Initialize the database with test data using
-i
- Change the bind address with
-b
- Change the port with
-p
Examples:
# Run in dev mode with test data
make run_dev
./dist/bin/captain-darwin-amd64 run -i
# Run on a different port
./dist/bin/captain-darwin-amd64 run -p 3000
# Bind to all interfaces
./dist/bin/captain-darwin-amd64 run -b 0.0.0.0
For production use, use the standard make run
command which disables debug mode.
Captain can be configured through environment variables or a YAML configuration file. Environment variables take precedence over the configuration file.
The config file can be specified using the -c
flag:
captain run -c /path/to/config.yaml
If the -c
flag is not provided, Captain will look for a config file named config.yaml
in the current directory or in /etc/captain/
.
Here's a complete configuration file with all available options:
# Server Configuration
server:
host: "localhost" # Listen address
port: 8080 # Listen port
# Database Configuration
db:
path: "blog.db" # SQLite database file path
log_level: "warn" # Database log level (silent, error, warn, info)
# Site Configuration
site:
theme: "default-light" # Theme name
secure_cookie: false # Use secure cookies (set to true when serving over HTTPS)
domain: "" # Cookie domain (e.g., "example.com") or empty for current domain
# Storage Configuration
storage:
provider: "local" # Storage provider: "local" or "s3"
local_path: "./media" # Path for local file storage (only for local provider)
# S3 Configuration (only required when provider is "s3")
s3:
bucket: "" # S3 bucket name
region: "" # AWS region (e.g., "us-east-1")
endpoint: "" # Optional: Custom endpoint for S3-compatible services
access_key: "" # S3 access key
secret_key: "" # S3 secret key
# Debug mode
debug: false
Configuration Key | Description | Default Value | Valid Values |
---|---|---|---|
server.host |
Server listen address | localhost |
Any valid IP or hostname |
server.port |
Server listen port | 8080 |
1-65535 |
db.path |
SQLite database file path | blog.db |
Any valid file path |
db.log_level |
Database logging verbosity | warn |
silent , error , warn , info |
site.theme |
Website theme | "" |
Any installed theme name |
site.secure_cookie |
Use secure cookies | false |
true , false (set to true when serving over HTTPS) |
site.domain |
Cookie domain | "" |
Domain name (e.g., "example.com") or empty for current domain |
storage.provider |
Storage provider type | local |
local , s3 |
storage.local_path |
Local storage path | ./media |
Any valid directory path |
storage.s3.bucket |
S3 bucket name | "" |
Valid S3 bucket name |
storage.s3.region |
S3 region | "" |
Valid AWS region (e.g., us-east-1) |
storage.s3.endpoint |
S3 endpoint URL | "" |
Valid URL for S3-compatible services |
storage.s3.access_key |
S3 access key | "" |
Valid AWS access key |
storage.s3.secret_key |
S3 secret key | "" |
Valid AWS secret key |
debug |
Enable debug mode | false |
true , false |
Note: Site settings such as title, subtitle, timezone, and admin theme can be configured through the admin panel under Settings.
Variable | Description | Default | Valid Values |
---|---|---|---|
CAPTAIN_DEBUG |
Enable debug mode | false |
true , false |
CAPTAIN_SERVER_HOST |
Host address to bind to | localhost |
Any valid IP or hostname |
CAPTAIN_SERVER_PORT |
Port number for the server | 8080 |
1-65535 |
CAPTAIN_DB_PATH |
SQLite database file location | blog.db |
Any valid file path |
CAPTAIN_DB_LOG_LEVEL |
Database logging verbosity | warn |
silent , error , warn , info |
CAPTAIN_STORAGE_PROVIDER |
Storage provider type | local |
local , s3 |
CAPTAIN_STORAGE_PATH |
Local storage path | ./uploads |
Any valid directory path |
CAPTAIN_SITE_SECURE_COOKIE |
Use secure cookies | false |
true , false (set to true when serving over HTTPS) |
CAPTAIN_SITE_DOMAIN |
Cookie domain | "" |
Domain name (e.g., "example.com") or empty for current domain |
CAPTAIN_S3_BUCKET |
S3 bucket name | "" |
Valid S3 bucket name |
CAPTAIN_S3_REGION |
S3 region | "" |
Valid AWS region (e.g., us-east-1) |
CAPTAIN_S3_ENDPOINT |
S3 endpoint URL | "" |
Valid URL for S3-compatible services |
CAPTAIN_S3_ACCESS_KEY |
S3 access key | "" |
Valid AWS access key |
CAPTAIN_S3_SECRET_KEY |
S3 secret key | "" |
Valid AWS secret key |
CAPTAIN_SITE_THEME |
Website theme name | "" |
Any installed theme name |
When CAPTAIN_DEBUG
is set to true
:
- Gin framework runs in debug mode with detailed logging
- GORM database logging is set to info level
- More detailed error messages are displayed
For production use, keep debug mode disabled.
Captain supports customizable themes for the public site. The admin interface maintains a consistent look regardless of the website theme selected.
When site.theme
is empty (""
), Captain uses its embedded default theme.
To use a custom theme:
- Create a directory in
themes/
with your theme name (e.g.,themes/mytheme/
) - Add the required theme files:
themes/mytheme/ ├── templates/ │ ├── header.tmpl │ ├── footer.tmpl │ ├── login.tmpl │ ├── page.tmpl │ ├── post.tmpl │ ├── posts.tmpl │ └── tag_posts.tmpl │ └── static/ ├── css/ │ └── main.css └── js/ └── main.js
- Set
site.theme: "mytheme"
in your config.yaml orCAPTAIN_SITE_THEME=mytheme
Custom themes can override any of the default templates and provide their own static assets.
Captain uses semantic versioning. You can check the current version by running:
captain version
To bump the version, use one of the following make commands:
make bump-major
- Bump major version (x.0.0)make bump-minor
- Bump minor version (0.x.0)make bump-patch
- Bump patch version (0.0.x)
Each version bump will:
- Update the version in version.go
- Create a git commit with the version change
- Create a git tag for the new version
This project is an AI-first experiment. While all contributions are welcome, we encourage:
- Using AI assistants (like GitHub Copilot) for code generation
- Documenting AI-human collaboration in pull requests
- Sharing insights about AI-assisted development
For detailed contribution guidelines, including our branch naming convention and pull request process, please see our CONTRIBUTING.md file.