A guide for spinning up your own instance of 0x0, a no-bullshit file hosting and URL shortening service.
0x0 (AKA "The Null Pointer") is a "no-bullshit file hosting and URL shortening service" that I've been using for a couple of months now. It's very easy to use, simple and straightforward. Although you can use the homepage of the project (0x0.st) for hosting files and shortening links, I'd like to tell you how did I spin up my own instance of 0x0 because (as the author of the project says) centralization is bad!
- Requirements
- Configuring 0x0
- Testing 0x0 with uWSGI
- Configuring uWSGI
- Creating a systemd unit file for uWSGI
- Configuring Nginx for proxying requests
- Getting an SSL certificate
- Using 0x0
- Conclusion
Requirements
- A server and preferably a domain. (I'll be using Ubuntu 20.04.1 from AWS Free Tier and a free domain)
- Linux dependencies: Nginx, Certbot, Python3
- Python dependencies: uWSGI, python-pip
- pip install -r requirements.txt
Configuring 0x0
Connect to your server via SSH and clone the repository:
cd $HOME/
git clone https://git.0x0.st/mia/0x0 && cd 0x0/
Then you can tweak some settings like maximum file size and storage path in fhost.py or in instance/config.py
.
Don't forget to create the configuration file and initialize the database before proceeding:
mkdir instance/
touch instance/config.py
python3 fhost.py db upgrade
Testing 0x0 with uWSGI
After you install uWSGI, you can simply test if 0x0 runs with the following command*:
uwsgi --socket 0.0.0.0:8080 --protocol=http --wsgi-file fhost.py --callable app
Note: If --wsgi-file
option is not recognized, make sure you have python plugin for uWSGI installed and loaded. *
You should be seeing the homepage of 0x0 at http://your_server_ip:8080
. If not, debug time...
Configuring uWSGI
Now we can create a configuration file for UWSGI to serve 0x0 more easily for production. Since this tutorial also suggests doing this, I don't see any reason to not do so!
$HOME/0x0/0x0.ini
[uwsgi]
wsgi-file = fhost.py
callable = app
master = true # Master mode
processes = 5 # Spawn 5 worker processes to serve requests
socket = 0x0.sock # Unix socket
chmod-socket = 660 # Socket permissions
vacuum = true # Clean up the socket when process exits
die-on-term = true # Shutdown if SIGTERM is received
Then you can use the -c
option for using this configuration file:
uwsgi -c 0x0.ini
Creating a systemd unit file for uWSGI
We can create a systemd unit file to start our service on boot. Something basic like this will do the job:
/etc/systemd/system/0x0.service
[Unit]
Description=uWSGI instance to serve 0x0
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/0x0
ExecStart=/home/ubuntu/.local/bin/uwsgi --ini 0x0.ini
[Install]
WantedBy=multi-user.target
Change ubuntu
to your $USER
and you can configure the rest as you like.
Start/enable the service:
sudo systemctl start 0x0
sudo systemctl enable 0x0
Check if it's running w/o errors:
sudo systemctl status 0x0
If you see any errors: debug time once again. My condolences.
Configuring Nginx for proxying requests
Now we can configure Nginx to pass requests to our Unix socket (0x0.sock
) via uwsgi
protocol.
First, let's create a server block configuration:
/etc/nginx/sites-available/0x0
server {
server_name your_domain www.your_domain;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/ubuntu/0x0/0x0.sock; # Unix socket location
}
location /up { # Upload directory (FHOST_STORAGE_PATH in fhost.py)
root /home/ubuntu/0x0; # Root of the upload directory
internal;
}
}
Enable the server block configuration:
sudo ln -s /etc/nginx/sites-available/0x0 /etc/nginx/sites-enabled
And lastly {re,}start Nginx to read the new configuration:
sudo systemctl restart nginx
If everything went well, you should be seeing your site up at http://your_domain
. If not, check the following:
sudo less /var/log/nginx/{error,access}.log
sudo journalctl -u {nginx,0x0}
Getting an SSL certificate
We can simply use Certbot to get an SSL certificate and secure our application. In order to do that, install Certbot and nginx
plugin:
sudo apt-get install certbot
sudo apt-get install python3-certbot-nginx
Then use nginx
plugin to create a new certificate:
sudo certbot --nginx -d your_domain -d www.your_domain
It's going to ask for some information and eventually reconfigure Nginx to use the newly created SSL certificate.
Add uwsgi_param UWSGI_SCHEME https;
to your server block config (for enforcing HTTPS) and your new server block might look like this at the end:
server {
server_name your_domain www.your_domain;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/ubuntu/0x0/0x0.sock;
uwsgi_param UWSGI_SCHEME https;
}
location /up {
root /home/ubuntu/0x0;
internal;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.your_domain) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = your_domain) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name your_domain www.your_domain;
return 404; # managed by Certbot
}
And voila! Your very own 0x0 instance is live at https://your_domain
.
Using 0x0
- For posting files:
curl -F'file=@yourfile.png' https://your_domain
- For posting remote URLs:
curl -F'url=http://example.com/image.jpg' https://your_domain
- For shortening URLs:
curl -F'shorten=http://example.com/some/long/url' https://your_domain
I recommend setting up aliases for these commands or using a wrapper script like this.
To make files expire, simply create a cronjob that runs cleanup.py
every now and then.
Conclusion
And here we have a "no-bullshit" file hosting and URL shortening service! Of course, we could've automated the process by writing a Dockerfile but it was my first significant attempt on these topics so I wanted to share my story by blogging it.
Feel free to contact me for improvements/fixes!
viel spaß! :)