PyBord
A lightweight, imageboard clone built with Flask.
License
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
Features
- Multiple discussion boards
- Thread creation and replies
- Image uploads with validation
- Rate limiting (10 posts per minute per IP)
- Proof-of-work CAPTCHA system
- Anonymous posting with optional tripcodes
- Quote references (>>123 for posts, #123 for threads)
- Responsive web interface
Architecture
PyBord
├── api/
│ └── routes/
│ └── main.py # Main application routes
├── config/
│ ├── config.py # Development config
│ ├── config_prod.py # Production config
│ └── gunicorn_config.py # Gunicorn server config
├── core/
│ ├── app.py # Flask application factory
│ └── utils/
│ ├── cache.py # Caching utilities
│ ├── captcha.py # CAPTCHA generation/validation
│ ├── sanitizer.py # File validation utilities
│ └── tripcodes.py # Tripcode generation
├── database/
│ └── models/
│ └── __init__.py # Database models (Board, Thread, Post)
├── frontend/
│ ├── static/ # Static assets (CSS, JS, images)
│ └── templates/ # HTML templates
├── scripts/
│ ├── manage.sh # Unified management script
│ ├── populate_db.py # Sample data generator
│ ├── test_exploits.py # Exploit test data generator
│ └── create_favicon.py # Favicon generator
├── dev_server.py # Development server
├── wsgi.py # WSGI entry point
└── requirements.txt # Python dependencies
Building
Prerequisites
- Python 3.11
- The pip package manager
- Docker and docker-compose (for container deployment)
Installation
- Clone the repository
- Create a virtual environment:
python -m venv venv - Activate the virtual environment:
source venv/bin/activate # On Linux/Mac # or venv\Scripts\activate # On Windows - Install dependencies:
pip install -r requirements.txt
Developing
Running locally
Start the development server:
bash scripts/manage.sh dev
The application will be available at http://localhost:5000
Testing
Run the test suite:
bash scripts/manage.sh test
Management Script
All functionality is available through a single management script:
bash scripts/manage.sh [command]
Commands:
dev- Start development serverprod- Start production server with Docker Composesetup- Setup directories and permissions for Dockerperms- Fix permissions for Docker volumesbuild- Build Docker imagesample- Populate database with sample dataexploits- Clear database and populate with exploit test datatest- Run test suitefavicon- Create faviconhelp- Show help message
Extending
Adding New Routes
Routes are defined in api/routes/main.py. To add a new route:
@bp.route('/new-feature')
def new_feature():
return render_template('new_feature.html')
Adding New Models
Models are defined in database/models/__init__.py. To add a new model:
class NewModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
Customizing Templates
Templates are located in frontend/templates/. The main templates are:
index.html- Board listingboard.html- Thread listingthread.html- Post viewingpost.html- Post creation
Docker
Building Container
Build the Docker image:
bash scripts/manage.sh build
Running in Production
Start in production mode:
bash scripts/manage.sh prod
Manual Docker Commands
Old-school build and run:
docker build -t pybord-app .
docker run -p 5000:5000 pybord-app
Database
Schema
The application uses three main models:
Board Table
| Column | Type | Constraints | Description |
|---|---|---|---|
| id | Integer | Primary Key | Unique identifier |
| name | String(50) | Unique, Indexed | Board identifier (e.g., 'g', 'v', 'b') |
| title | String(100) | Not Null | Board title (e.g., 'Technology', 'Video Games') |
| description | Text | Board description | |
| created_at | DateTime | Indexed | Creation timestamp |
Thread Table
| Column | Type | Constraints | Description |
|---|---|---|---|
| id | Integer | Primary Key | Unique identifier |
| board_id | Integer | Foreign Key, Indexed | References Board.id |
| subject | String(200) | Thread subject/title | |
| created_at | DateTime | Indexed | Creation timestamp |
| bumped_at | DateTime | Indexed | Last post time |
| is_locked | Boolean | Indexed | Lock status |
| is_deleted | Boolean | Indexed | Deletion flag |
Post Table
| Column | Type | Constraints | Description |
|---|---|---|---|
| id | Integer | Primary Key | Unique identifier |
| thread_id | Integer | Foreign Key, Indexed | References Thread.id |
| content | Text | Not Null | Post content |
| author_name | String(100) | Indexed | Poster name |
| tripcode | String(20) | Generated from password | |
| ip_address | String(45) | Indexed | Anonymized IP hash |
| created_at | DateTime | Indexed | Creation timestamp |
| is_deleted | Boolean | Indexed | Deletion flag |
| filename | String(200) | Original filename | |
| file_path | String(300) | Stored file path | |
| file_size | Integer | File size in bytes | |
| file_hash | String(64) | Indexed | SHA-256 hash for duplicates |
Migration
The application uses SQLAlchemy for database operations. Tables are created automatically on first run.
Configuration
Environment Variables
FLASK_ENV- Set to 'development' or 'production' (defaults to 'production')DATABASE_URL- Database connection string (defaults to SQLite)SECRET_KEY- Secret key for session managementCAPTCHA_DIFFICULTY- Number of leading zeros required in proof-of-work (default: 3)
Settings
Configuration is managed in config/ directory:
config.py- Development settingsconfig_prod.py- Production settings
Security
- Rate limiting: 10 posts per minute per IP
- Proof-of-work CAPTCHA to prevent spam
- File upload validation with type checking
- SQL injection prevention through parameterized queries
- XSS protection through content sanitization
- Security headers applied to all responses