219 lines
6.7 KiB
Markdown
219 lines
6.7 KiB
Markdown
# Self-Hosted Blog Platform
|
|
|
|
A secure, privacy-focused blogging starter kit that keeps your data away from big tech. Deploy a complete blog platform with version control, analytics, and security in minutes.
|
|
|
|
## What This Is
|
|
|
|
A **self-hosted starter kit** for creating blogs that are safer and respect end-users without dependencies on big tech platforms. Entirely free and open source. Do What the Fuck You Want To Public License (Standard WTFPLv2), plus the licenses of the underlying software.
|
|
|
|
**For 99% of users**: A fast, secure blog with no ads, no tracking, and complete data ownership.
|
|
|
|
**For developers**: A Jekyll-based static site generator with modern DevOps practices baked in.
|
|
|
|
**For privacy advocates**: 1st party analytics, no cookies, and complete control over your data.
|
|
|
|
## Features
|
|
|
|
- **🚀 Jekyll**: Static site generator with automated builds. Less-style Theme fork included.
|
|
- **🔒 Traefik**: Reverse proxy for segmentation with automatic SSL, security headers, and IP allowlisting
|
|
- **📊 Umami**: Privacy-focused analytics (no cookies, 1st party data)
|
|
- **🛡️ CrowdSec**: Crowdsourced WAF with real-time threat intelligence
|
|
- **📝 Jekyll Admin**: WYSIWYG markdown editor so your boss's nephew can ~~justify his existence~~ write blog posts.
|
|
- **🔧 Forgejo**: Self-hosted Git platform for version control
|
|
- **⚡ Nginx**: High-performance static file serving
|
|
- **🔐 Security**: IP allowlisting, TLS certificates, and redundant access controls
|
|
|
|
## Who This Is For
|
|
|
|
This platform satisfies the needs of four key audiences:
|
|
|
|
### 🧑💻 Developers
|
|
- Trusted Jekyll ecosystem with static deployment
|
|
- Runs efficiently on small cloud instances
|
|
- Version control through Forgejo (optional but included)
|
|
- Docker-based deployment for consistency
|
|
|
|
### ✍️ Content Creators
|
|
- WYSIWYG Markdown editor with live preview
|
|
- SEO optimizations built-in
|
|
- Automated site building on content changes
|
|
- Separate dev/prod environments
|
|
|
|
### 📈 Analytics & Data Teams
|
|
- 1st party analytics without cookies
|
|
- Complete data ownership
|
|
- Privacy-compliant user tracking
|
|
- No dependency on Google Analytics
|
|
|
|
### 🔒 Security Teams
|
|
- Crowdsourced WAF protection
|
|
- IP allowlisting for admin interfaces
|
|
- Automatic TLS certificate management
|
|
- Redundant access controls
|
|
|
|
## Quick Start
|
|
|
|
1. **Clone and configure**:
|
|
```bash
|
|
git clone <this-repo>
|
|
cd self-hosted-blog
|
|
cp .env.example .env
|
|
vim .env # Configure your domain and settings
|
|
```
|
|
|
|
2. **Deploy**:
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
3. **Access your services**:
|
|
- **Blog**: `https://yourdomain.com` (public)
|
|
- **Admin**: `https://admin.yourdomain.com:333` (IP restricted)
|
|
- **Analytics**: `https://analytics.yourdomain.com:333` (IP restricted)
|
|
- **Git**: `https://git.yourdomain.com:333` (IP restricted)
|
|
|
|
## System Requirements
|
|
|
|
- **Minimum**: 1 shared CPU, 2GB RAM
|
|
|
|
Tested successfully on Linode shared instances.
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
Key variables to configure in your `.env` file:
|
|
|
|
```bash
|
|
# Domain Configuration for Routes and LetsEncrypt
|
|
DOMAIN=yourdomain.com
|
|
EMAIL=admin@yourdomain.com
|
|
|
|
# Security
|
|
TRUSTED_IPS=192.168.1.0/24,10.0.0.0/8 # Your allowed IP ranges
|
|
JEKYLL_ADMIN_USER_PASS=admin:$2y$10$... # Generated with htpasswd
|
|
|
|
# SSL Configuration (Linode DNS example)
|
|
LINODE_API_KEY=your_linode_api_key
|
|
|
|
# Analytics
|
|
UMAMI_PG_PWD=secure_password_here
|
|
UMAMI_HASH_SALT=random_salt_here
|
|
|
|
# CrowdSec
|
|
CROWDSEC_BOUNCER_API_KEY=your_crowdsec_key
|
|
```
|
|
|
|
### DNS & Firewall Setup
|
|
|
|
1. **DNS Records**: Point your domain and subdomains to your server IP
|
|
2. **Firewall**:
|
|
- Open ports 80, 443 (public)
|
|
- Restrict port 333 to trusted IPs only
|
|
3. **SSL**: Configured automatically via Let's Encrypt
|
|
|
|
## Content Management
|
|
|
|
### Creating Content
|
|
|
|
**Option 1: Web Interface** (Recommended)
|
|
- Access Jekyll Admin at `https://admin.yourdomain.com:333/admin`
|
|
- Create/edit posts with live preview
|
|
- Automatic site rebuilding
|
|
|
|
**Option 2: Direct File Editing**
|
|
- Edit files in `sites/jekyll-source/_posts/`
|
|
- Follow naming: `YYYY-MM-DD-title.md`
|
|
- Add front matter for metadata
|
|
|
|
### Jekyll Build Environments
|
|
|
|
Control build targets with the `BUILD_TARGET` environment variable:
|
|
|
|
- `BUILD_TARGET=prod` - Production site only
|
|
- `BUILD_TARGET=dev` - Development site only
|
|
- `BUILD_TARGET=both` - Both environments
|
|
|
|
## Security Features
|
|
|
|
### Multi-Layer Protection
|
|
|
|
1. **Network Level**: Cloud provider firewall + IP allowlisting
|
|
2. **Application Level**: Traefik IP allowlisting + basic auth
|
|
3. **WAF Level**: CrowdSec real-time threat detection
|
|
4. **Transport Level**: Automatic TLS with security headers
|
|
|
|
### Admin Interface Security
|
|
|
|
- **IP Allowlisting**: Only trusted IPs can access admin interfaces
|
|
- **Custom Port**: Non-standard port 333 for admin access
|
|
- **Basic Auth**: HTTP authentication for Jekyll Admin
|
|
- **TLS**: All traffic encrypted with Let's Encrypt certificates
|
|
|
|
### Best Practices
|
|
|
|
- Use a VPN for remote administration
|
|
- Regularly update the trusted IP list
|
|
- Monitor CrowdSec logs for blocked attempts
|
|
- Keep Docker images updated
|
|
|
|
## Customization
|
|
|
|
### Changing Jekyll Theme
|
|
|
|
1. Edit `sites/jekyll-source/Gemfile`
|
|
2. Update `_config.yml` theme setting
|
|
3. Run `bundle install` in the Jekyll container
|
|
|
|
### Adding Custom CSS/JS
|
|
|
|
- CSS: Edit `assets/css/style.scss`
|
|
- JavaScript: Edit `assets/js/custom.js`
|
|
|
|
### Modifying Services
|
|
|
|
The Docker Compose stack is modular. Remove or modify services as needed:
|
|
|
|
- Don't need Git? Remove the `forgejo` service
|
|
- Want different analytics? Replace `umami` with your preferred solution
|
|
- Need additional security? Add more CrowdSec collections
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
**Can't access admin interfaces**:
|
|
- Check your IP is in `TRUSTED_IPS`
|
|
- Verify firewall rules on your cloud provider
|
|
- Ensure port 333 is accessible from your location
|
|
|
|
**SSL certificate errors**:
|
|
- Verify DNS records are pointing to your server
|
|
- Check API credentials for your DNS provider
|
|
- Review Traefik logs: `docker logs mf-traefik`
|
|
|
|
**Site not building**:
|
|
- Check Jekyll container logs: `docker logs jekyll-builder`
|
|
- Verify file permissions in `sites/jekyll-source/`
|
|
- Ensure `BUILD_TARGET` is set correctly
|
|
- Ensure your nginx volume is mounted at the correct site directory
|
|
|
|
### Getting Help
|
|
|
|
1. Check container logs: `docker logs <container-name>`
|
|
2. Verify service status: `docker ps`
|
|
3. Review configuration files for syntax errors
|
|
4. Check DNS resolution: `nslookup yourdomain.com`
|
|
|
|
## Contributing
|
|
|
|
This is a starter kit meant to be forked and customized. Take what you need, modify or remove everything else.
|
|
|
|
**Known Issues**:
|
|
- Jekyll Admin interface may show harmless error messages
|
|
- Some themes may require additional configuration
|
|
- Mobile responsiveness varies by theme choice
|
|
|
|
## License
|
|
|
|
Open source - take it, modify it, make it yours.
|