Ansible role — null-pointer (0x0.st) file sharing on null.avallon.pw
|
|
||
|---|---|---|
| defaults | ||
| files | ||
| handlers | ||
| tasks | ||
| templates | ||
| README.md | ||
setup-null-pointer
Deploys 0x0.st — self-hosted null pointer file sharing service.
Service: null.avallon.pw
Stack: Flask + gunicorn + nginx (x-accel-redirect) + Let's Encrypt
Install path: /opt/null-pointer
Quick start
- Add host to inventory under group
null-pointer - Set in
host_vars/<host>/vars.yml:null_pointer_le_email: "admin@avallon.pw" null_pointer_secret_key: "{{ vault_null_pointer_secret_key }}" - Set in
host_vars/<host>/vault.yml:vault_null_pointer_secret_key: "<generate with: python -c 'import secrets; print(secrets.token_hex(32))'>" - Create DNS A record:
null.avallon.pw → <vps-ip> - Run:
ansible-playbook playbooks/setup-null-pointer.yml
Usage after deployment
# Upload file
curl -F'file=@yourfile.png' https://null.avallon.pw
# Upload with secret URL
curl -F'file=@yourfile.png' -Fsecret= https://null.avallon.pw
# Set custom expiry (hours)
curl -F'file=@yourfile.png' -Fexpires=24 https://null.avallon.pw
# Prune expired files (run periodically via cron)
docker exec null-app sh -c "FLASK_APP=fhost flask prune"
Key variables
| Variable | Default | Description |
|---|---|---|
null_pointer_domain |
null.avallon.pw |
Public domain |
null_pointer_install_dir |
/opt/null-pointer |
Install path |
null_pointer_le_email |
"" |
LE cert email (required) |
null_pointer_secret_key |
CHANGE_ME |
Flask secret (required) |
null_pointer_max_upload_mb |
256 |
Max upload size in MiB |
null_pointer_min_expiry_days |
30 |
Min file retention days |
null_pointer_max_expiry_days |
365 |
Max file retention days |
null_pointer_force_recreate |
false |
Force container recreate |
Architecture
client → nginx:443 → null-app:5000 (Flask/gunicorn)
↓
X-Accel-Redirect: nginx serves /app/up/* directly
nginx and app share the uploads volume at /app/up — nginx bypasses Flask for downloads via X-Accel-Redirect, Flask handles only uploads and URL generation.