Skip to content

DevURANIUM/cText

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

cText πŸ“‹

A fast, minimal, and secure pastebin alternative β€” built with FastAPI.

cText lets you share text snippets privately and securely. Pastes are encrypted at rest, can be password-protected, and automatically expire. No accounts, no tracking, no ads.


πŸ†• What's New

  • πŸ”’ Code type selector β€” choose how the paste code (URL) is generated: numbers only, letters + numbers, or letters only. Thanks to @hujigko for the idea and help.
  • πŸ•’ Local timezone β€” expiry times are now shown in Asia/Tehran local time instead of UTC.
  • 🎨 UI polish β€” refined dark dropdowns on mobile, a new neon grid background, and an optional light theme.

✨ Features

  • πŸ” End-to-end encryption β€” paste content is encrypted at rest using Fernet (AES-128-CBC)
  • πŸ”‘ Password protection β€” optional bcrypt-hashed password per paste
  • ⏳ Auto-expiry β€” choose expiration from 10 minutes up to 30 days
  • πŸ”’ Code type selector β€” generate paste codes as numbers, letters, or both
  • πŸ›‘οΈ CSRF protection β€” HMAC-based CSRF tokens on all forms
  • πŸ“„ Raw view β€” direct plaintext access via /raw/{id}
  • πŸ—‘οΈ Manual delete β€” delete your paste at any time
  • 🧹 Auto-cleanup β€” daily cron job removes expired pastes
  • 🚫 No registration required β€” completely anonymous usage
  • 🌐 HTTPS-first β€” designed to run behind Nginx with Let's Encrypt SSL

πŸ› οΈ Tech Stack

Layer Technology
Backend FastAPI + Uvicorn
ORM SQLAlchemy
Database SQLite
Encryption Cryptography (Fernet)
Password Hashing bcrypt
Sessions Starlette SessionMiddleware
Templating Jinja2
Reverse Proxy Nginx
Process Manager Systemd
SSL Let's Encrypt (Certbot)

πŸ“ Project Structure

ctext/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ main.py          # FastAPI routes and application logic
β”‚   β”œβ”€β”€ models.py        # SQLAlchemy models
β”‚   β”œβ”€β”€ db.py            # Database session setup
β”‚   β”œβ”€β”€ static/          # CSS, JS, assets
β”‚   └── templates/       # Jinja2 HTML templates
β”‚       β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ view.html
β”‚       β”œβ”€β”€ created.html
β”‚       └── 404.html
β”œβ”€β”€ cleanup_expired.py   # Standalone cleanup script (used by cron)
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ .env                 # Secret keys (not committed)
└── pastes.db            # SQLite database (auto-created)

βš™οΈ Installation & Deployment

Prerequisites

  • Ubuntu 22.04+ (or similar Debian-based distro)
  • Python 3.10+
  • Nginx
  • Certbot (for SSL)
  • A domain pointing to your server

1. Update Server

apt update -y && apt upgrade -y && apt autoremove -y

2. Install System Dependencies

sudo apt install -y python3 python3-pip nginx

If you encounter conflicts with typing-extensions:

apt remove --purge python3-typing-extensions

3. Clone & Set Up Project

mkdir /var/www/ctext/
cd /var/www/ctext/
git clone https://github.com/DevURANIUM/cText.git .
pip install -r requirements.txt --break-system-packages

4. Configure Environment Variables

Create the .env file:

nano /var/www/ctext/.env

Add the following:

PASTE_SECRET_KEY=
SESSION_SECRET_KEY=
CSRF_SESSION_KEY=

How to generate each key:

# PASTE_SECRET_KEY (Fernet key β€” must be this exact format)
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

# SESSION_SECRET_KEY (random URL-safe string)
python3 -c "import secrets; print(secrets.token_urlsafe(64))"

# CSRF_SESSION_KEY (just a session key name, e.g. a short string)
python3 -c "import secrets; print(secrets.token_urlsafe(64))"

Example .env after filling in:

PASTE_SECRET_KEY=Ib7k2YourGeneratedFernetKeyHere=
SESSION_SECRET_KEY=yourLongRandomSessionSecretHere
CSRF_SESSION_KEY=csrf_token

⚠️ Never commit .env to version control. Add it to .gitignore.


5. Configure Systemd Service

Create /etc/systemd/system/ctext.service:

[Unit]
Description=ctext FastAPI application
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/ctext

EnvironmentFile=/var/www/ctext/.env

ExecStart=/usr/local/bin/uvicorn app.main:app \
  --host 127.0.0.1 \
  --port 8001 \
  --proxy-headers

Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl start ctext
sudo systemctl enable ctext
sudo systemctl status ctext

6. Configure Nginx

Create /etc/nginx/sites-available/ctext.ir:

server {
    listen 80;
    server_name ctext.ir;

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/ctext.ir /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

7. Enable SSL (Let's Encrypt)

sudo certbot --nginx -d ctext.ir
sudo certbot renew --dry-run

8. Fix File Permissions

chown www-data:www-data /var/www/ctext/pastes.db
chmod 664 /var/www/ctext/pastes.db
chown www-data:www-data /var/www/ctext
chmod 775 /var/www/ctext

9. Set Timezone (Optional)

sudo timedatectl set-timezone Asia/Tehran

The app also resolves time using the Asia/Tehran zone internally (via zoneinfo), so paste expiry times are shown in local time regardless of the host setting.


10. Configure Cron Job (Cleanup)

Run crontab -e and add:

# Run cleanup every day at 03:00 AM
0 3 * * * cd /var/www/ctext && /usr/bin/python3 cleanup_expired.py >> /var/www/ctext/ctext_cleanup.log 2>&1

Verify:

crontab -l

πŸ—οΈ Architecture

Client (Browser)
       β”‚
       β–Ό
  Nginx :80/:443  ──── SSL termination (Let's Encrypt)
       β”‚
       β–Ό
 Uvicorn :8001 (127.0.0.1 only)
       β”‚
       β–Ό
 FastAPI Application
       β”‚
       β–Ό
  SQLite (pastes.db)
  • Nginx handles all public traffic and TLS
  • Uvicorn binds only to localhost for security
  • Systemd ensures the process restarts automatically on failure

πŸ”’ Security Notes

  • Paste content is encrypted at rest using Fernet symmetric encryption
  • Passwords are hashed with bcrypt (12 rounds); passwords longer than 72 bytes are SHA-256-prehashed before bcrypt to prevent truncation
  • CSRF tokens are signed using hmac.compare_digest to prevent timing attacks
  • Sessions use SameSite=Lax and https_only=True
  • The application process runs as www-data (least privilege)
  • Uvicorn binds only to 127.0.0.1 β€” never exposed directly to the internet

βœ… Final Checks

sudo systemctl status ctext
sudo nginx -t
sudo certbot renew --dry-run

Your application will be live at:

https://ctext.ir

πŸ“¦ Requirements

fastapi
uvicorn
gunicorn
jinja2
sqlalchemy
python-dotenv
python-multipart
bcrypt
cryptography
itsdangerous

Install with:

pip install -r requirements.txt --break-system-packages

πŸ™ Acknowledgements

  • @hujigko β€” for the idea and help with the Code type feature, which added the option to generate paste codes as numbers, letters, or both.

πŸ’› Support the Project

If cText is useful to you, consider supporting its development:

Network Address
BTC bc1qcclcp574hnznm0nmdzzf0ta7366svjskttqks3
LTC ltc1qcrkelw38gjrmg0ptjy2nshqej622kp76het7q0
XRP rPoK5SBChFPqEiQv1W97LW6FKoJZLipDVQ
XLM GDMUQREEZNBSTQOT5BV7MYEMXJFV3CYRZXUVOYCTIUZTHUWPHLVASFVD
TON UQAJH2N0pqpvC9YN841w5NH1dCN9Lakwkpjvoy7vXf-vfqgv
TRON TXJqhhwvkrTdnf5HReZf55hEzZuxjto3R4
USDT (BEP20) 0x1591036c4bD05b046532B65Df939fcd7824E18c7

Every contribution, no matter how small, helps keep the project running. ❀️


πŸ“„ License

This project is open source. See LICENSE for details.

About

A simple and lightweight Pastebin alternative (cText) for quickly sharing text, code, and logs without relying on external services. Designed for speed, minimalism, and easy self-hosting.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors