| title | GitHub Setup Guide |
|---|---|
| description | Configure GitHub Actions for automatic Docker builds and documentation deployment for Charon. |
This guide will help you set up GitHub Actions for automatic Docker builds and documentation deployment.
The Docker build workflow uses GitHub Container Registry (GHCR) to store your images. No setup required! GitHub automatically provides authentication tokens for GHCR.
GitHub Actions automatically uses the built-in secret token to authenticate with GHCR. We recommend creating a GITHUB_TOKEN secret (preferred); workflows currently still work with CHARON_TOKEN for backward compatibility.
- ✅ Push images to
ghcr.io/wikid82/charon - ✅ Link images to your repository
- ✅ Publish images for free (public repositories)
Nothing to configure! Just push code and images will be built automatically.
By default, container images are private. To make them public:
- Go to your repository → https://github.com/Wikid82/charon
- Look for "Packages" on the right sidebar (after first build)
- Click your package name
- Click "Package settings" (right side)
- Scroll down to "Danger Zone"
- Click "Change visibility" → Select "Public"
Why make it public? Anyone can pull your Docker images without authentication!
Your documentation will be published to GitHub Pages (not the wiki). Pages is better for auto-deployment and looks more professional!
- Go to your repository → https://github.com/Wikid82/charon
- Click "Settings" (top menu)
- Click "Pages" (left sidebar under "Code and automation")
- Under "Build and deployment":
- Source: Select "GitHub Actions" (not "Deploy from a branch")
- That's it! No other settings needed.
Once enabled, your docs will be live at:
https://wikid82.github.io/charon/
Note: The first deployment takes 2-3 minutes. Check the Actions tab to see progress!
E2E tests require an emergency token to be configured in GitHub Secrets. This token allows tests to bypass security modules during teardown.
The emergency token is used by E2E tests to:
- Disable security modules (ACL, WAF, CrowdSec) after testing them
- Prevent cascading test failures due to leftover security state
- Ensure tests can always access the API regardless of security configuration
-
Generate emergency token:
Linux/macOS:
openssl rand -hex 32
Windows PowerShell:
[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
Node.js (all platforms):
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Copy the output (64 characters for hex, or appropriate length for base64)
-
Navigate to repository secrets:
- Go to:
https://github.com/<your-username>/charon/settings/secrets/actions - Or: Repository → Settings → Secrets and Variables → Actions
- Go to:
-
Create new secret:
- Click "New repository secret"
- Name:
CHARON_EMERGENCY_TOKEN - Value: Paste the generated token
- Click "Add secret"
-
Verify secret is set:
- Secret should appear in the list
- Value will be masked (cannot view after creation for security)
The E2E workflow automatically validates the emergency token:
- name: Validate Emergency Token Configuration
run: |
if [ -z "$CHARON_EMERGENCY_TOKEN" ]; then
echo "::error::CHARON_EMERGENCY_TOKEN not configured"
exit 1
fiIf the secret is missing or invalid, the workflow will fail with a clear error message.
Recommended schedule: Rotate quarterly (every 3 months)
Rotation steps:
- Generate new token (same method as above)
- Update GitHub Secret:
- Settings → Secrets → Actions
- Click on
CHARON_EMERGENCY_TOKEN - Click "Update secret"
- Paste new value
- Save
- Update local
.envfile (for local testing) - Re-run E2E tests to verify
✅ DO:
- Use cryptographically secure generation methods
- Rotate quarterly or after security events
- Store separately for local dev (
.env) and CI/CD (GitHub Secrets)
❌ DON'T:
- Share tokens via email or chat
- Commit tokens to repository (even in example files)
- Reuse tokens across different environments
- Use placeholder or weak values
Error: "CHARON_EMERGENCY_TOKEN not set"
- Check secret name is exactly
CHARON_EMERGENCY_TOKEN(case-sensitive) - Verify secret is repository-level, not environment-level
- Re-run workflow after adding secret
Error: "Token too short"
- Hex method must generate exactly 64 characters
- Verify you copied the entire token value
- Regenerate if needed
📖 More Info: See E2E Test Troubleshooting Guide
Prerequisites:
- go 1.26.0+ (automatically managed via
GOTOOLCHAIN: autoin CI) - Node.js 20+ for frontend builds
Triggers when:
- ✅ You push to
mainbranch → Createslatesttag - ✅ You push to
developmentbranch → Createsdevtag - ✅ You create a version tag like
v1.0.0→ Creates version tags - ✅ You manually trigger it from GitHub UI
What it does:
- Builds the frontend
- Builds a Docker image for multiple platforms (AMD64, ARM64)
- Pushes to Docker Hub with appropriate tags
- Tests the image by starting it and checking the health endpoint
- Shows you a summary of what was built
Tags created:
latest- Always the newest stable version (frommain)dev- The development version (fromdevelopment)1.0.0,1.0,1- Version numbers (from git tags)sha-abc1234- Specific commit versions
Where images are stored:
ghcr.io/wikid82/charon:latestghcr.io/wikid82/charon:devghcr.io/wikid82/charon:1.0.0
Triggers when:
- ✅ You push changes to
docs/folder - ✅ You update
README.md - ✅ You manually trigger it from GitHub UI
What it does:
- Converts all markdown files to beautiful HTML pages
- Creates a nice homepage with navigation
- Adds dark theme styling (matches the app!)
- Publishes to GitHub Pages
- Shows you the published URL
-
Make a small change to any file
-
Commit and push to
development:git add . git commit -m "test: trigger docker build" git push origin development
-
Go to Actions tab on GitHub
-
Watch the "Build and Push Docker Images" workflow run
-
Check Packages on your GitHub profile for the new
devtag!
-
Make a small change to
README.mdor any doc file -
Commit and push to
main:git add . git commit -m "docs: update readme" git push origin main
-
Go to Actions tab on GitHub
-
Watch the "Deploy Documentation to GitHub Pages" workflow run
-
Visit your docs site (shown in the workflow summary)!
When you're ready to release a new version:
-
Tag your release:
git tag -a v1.0.0 -m "Release version 1.0.0" git push origin v1.0.0 -
The workflow automatically:
- Builds Docker image
- Tags it as
1.0.0,1.0, and1 - Pushes to Docker Hub
- Tests it works
-
Users can pull it:
docker pull ghcr.io/wikid82/charon:1.0.0 docker pull ghcr.io/wikid82/charon:latest
Problem: "Error: denied: requested access to the resource is denied"
- Fix: This shouldn't happen with
GITHUB_TOKENorCHARON_TOKEN- check workflow permissions - Verify: Settings → Actions → General → Workflow permissions → "Read and write permissions" enabled
Problem: Can't pull the image
- Fix: Make the package public (see Step 1 above)
- Or: Authenticate with GitHub:
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin(orCHARON_TOKENfor backward compatibility)
Problem: "deployment not found"
- Fix: Make sure you selected "GitHub Actions" as the source in Pages settings
- Not: "Deploy from a branch"
Problem: Docs show 404 error
- Fix: Wait 2-3 minutes after deployment completes
- Fix: Check the workflow summary for the actual URL
Check workflow logs:
- Go to Actions tab
- Click the failed workflow
- Click the failed job
- Expand the step that failed
- Read the error message
Still stuck?
- Open an issue: https://github.com/Wikid82/charon/issues
- We're here to help!
# Pull latest development version
docker pull ghcr.io/wikid82/charon:dev
# Pull stable version
docker pull ghcr.io/wikid82/charon:latest
# Pull specific version
docker pull ghcr.io/wikid82/charon:1.0.0
# Run the container
docker run -d -p 8080:8080 -v caddy_data:/app/data ghcr.io/wikid82/charon:latest# Create a new version tag
git tag -a v1.2.3 -m "Release 1.2.3"
# Push the tag
git push origin v1.2.3
# List all tags
git tag -l
# Delete a tag (if you made a mistake)
git tag -d v1.2.3
git push origin :refs/tags/v1.2.3- Go to Actions tab
- Click the workflow name (left sidebar)
- Click "Run workflow" button (right side)
- Select branch
- Click "Run workflow"
Before pushing to production, make sure:
- GitHub Pages is enabled with "GitHub Actions" source
- You've tested the Docker build workflow (automatic on push)
- You've tested the docs deployment workflow
- Container package is set to "Public" visibility (optional, for easier pulls)
- Documentation looks good on the published site
- Docker image runs correctly
- You've created your first version tag
Your CI/CD pipeline is now fully automated! Every time you:
- Push to
main→ NewlatestDocker image + updated docs - Push to
development→ NewdevDocker image for testing - Create a tag → New versioned Docker image
No manual building needed! 🚀
Questions? Check the GitHub Actions docs or open an issue!