Introduction

I have gotten increasingly into small tech over the years, and in March 2026 I finally took the plunge into the world of the Raspberry Pi.

The Raspberry Pi is a Single-Board Computer (SBC) released in 2012 by the Raspberry Pi Foundation. As of writing it's the best-selling British computer, surpassing the ZX Spectrum only three years after its launch.

The Pi was originally designed to teach computer science, but has since become a metaphorical zen garden for all manner of tech projects. As it's compact in size and consumes little energy, this makes it an ideal choice for 24/7 operations such as webservers and chatrooms. Its operating system, the Raspberry Pi OS, is a Linux-based OS. As a result, Pi-work is designed with tech enthusiasts in mind and isn't a tool for casual users. To use a Pi, you have to be comfortable using a terminal and with the prospect of learning some degree of Linux.

Getting a Pi

Given the low-power nature of my services, I made the more conservative choice of the Pi 4B. I purchased this from The Pi Hut, which is the most popular UK vendor for Raspberry Pis. The delivery on Pi Hut is honestly one of the fastest I have ever had from an e-vendor, even if I had to click for Royal Mail rather than have the poor thing chucked about by Evri (formerly Hermes).White micro-HDMI to HDMI cable. Because I didn't realise my black USB cable wasn't a micro HDMI one. This is for establishing a display on your spare desktop monitor, which you'll need for navigating the Pi setup.

What Arrived in the Post

Raspberry Pi 4 Model B. I purchased the 2GB option, but you can buy Pis available with up to 8GB of RAM.

Official 32GB SD card (pre-loaded with 64-bit Raspberry Pi OS). This one was pre-loaded with the Pi OS, thus saving me from having to flash it to the card manually. The latter process isn't covered in this guide.

Official Raspberry Pi power supply (white UK plug). Always use the official Raspberry Pi power supplies. Using anything else can underpower your Pi.

A black USB cable. This cable came as a bonus, but was ultimately left unused during my setup. It's still good to keep around as a spare.

Official black/grey case, complete with an embossed Pi logo. This protects the Pi's circuit board from dust, static, and physical damage. You can probably put a few little stickers on it.

Step 1: The Scene

Spare monitor. An Acer was used for this initial setup.Starting a Pi can't be done from your main device. You need extra hardware, as you're temporarily making a miniature desktop setup. If you're low on supplies, you can unplug things from your main setup. Expect the main setup to fall asleep if it has been left on. Putting a mouse or keyboard back in won't automatically wake it up.

Spare keyboard. A spare Dell keyboard from a late Christmas gift worked nicely here.

Spare mouse. A Razer mouse was used, as there were no spare mice on hand.

Step 2: Checklist

Before proceeding, make sure you've all of the following:

  • Your Pi's micro SD card (pre-loaded with 64-bit Raspberry Pi OS)
  • Your Pi's microHDMI cable
  • Your Pi's power supply
  • Your Pi's protective case
  • Your Raspberry Pi
  • A spare keyboard
  • A spare monitor
  • A spare mouse

Once you've got all of these, you're ready to assemble your Pi.

Step 1: Inserting the SD Card

  1. Slot the Pi into the bottom half of its case. Press on the flat circuit board parts of the Pi until it makes a nice snapping sound. Don't be shy, it can handle this even if it looks like it can't.

  2. The SD card slot is located on the underside of the Pi board, on the other side of the USB ports. With your Pi in one hand and your Micro SD in the other, slot it gently into the Pi. The gold contacts have to face up towards you and the board it's entering, while the label side faces underneath. If the card keeps entering at an angle, you're likely trying to insert the wrong side.

  3. Push gently until it clicks. It should not be at an angle or stick out past the edge of the bottom case.

  4. Slot the top case onto the Pi.

You've now loaded your Raspberry Pi. The SD card is crucial to doing anything with the Pi and it must always be handled carefully.

Step 2: Connecting Cables and Power

  1. Spare keyboard into any USB port on the Pi.

  2. Mouse into any USB port on the Pi.

  3. White HDMI cable: the small micro-HDMI end goes into the Pi. Use the port closest to the power port. The normal HDMI end goes into the spare monitor.

  4. Make sure the spare monitor is plugged in and turned on.

  5. Plug the power supply into the Pi's USB-C port last.

When you plug in the power, the Pi will turn on and your spare monitor should start doing things.

Step 3: Navigating the Wizard

  1. Let the Pi boot up. It should start with a black screen, then a rainbow gradient, and finally the Raspberry Pi welcome screen. This is light-mode only so don't do this in the dark.

  2. You're now in the Raspberry Pi Setup Wizard. Like other Setup Wizards, this will walk you through the installation and help you create an account for your Pi.

  3. Set your language, region and timezone.

  4. User Account: the username must be lowercase letters, digits, and hyphens only. Make sure it's easy enough to type comfortably. Write everything down somewhere safe as you go, your username, your password, and later your IP address. Nothing appears on screen when typing your password. This is normal.

  5. Network: connect to WiFi, or skip if you're using ethernet.

  6. Reboot: accept any reboot requests.

Step 4: Enabling SSH Access

Secure Shell Protocol lets you control the Pi from your main computer without needing the extra desktop setup. This is known as a headless setup, and is common practice amongst Pi users.

  1. Click the terminal icon, the black monitor icon in the top toolbar.

  2. Type: sudo raspi-config and press Enter.

  3. It'll ask for the password you set up in the wizard. If you can't see it while typing, this is normal and common in terminals.

  4. A blue menu should appear. Use your keyboard's arrow keys to go to 3 Interface Options and press Enter.

  5. Navigate to the option for SSH and select it. Select Yes when asked if you would like the SSH server to be enabled.

  6. Press Tab to highlight Finish and press Enter to select.

  7. To check your SSH is working, type: sudo systemctl status ssh. You should see "active (running)" in the output.

  8. Press Q to exit. Your SSH is now established.

Step 5: Getting Your Pi's IP Address

You're almost done with the setup, but if you stop here you won't be able to access your Pi remotely. The last thing you need is your Pi's IP address, which you enter every time you want to access it.

  1. In the terminal, type: hostname -I

  2. Note the number it shows. This is your Pi's IP address, and tends to differ slightly from your main computer's.

  3. You now have your Pi's IP address.

IP addresses can sometimes change for a variety of reasons. If you can't SSH into your Pi, you'll need to repeat this process.

Safely Turning Off Your Pi

Now that you've established your brand new Pi and written down its information, you're free to stop from here. However, you've probably noticed that your Pi lacks the conventional means of shut-down.

Step 6: Proper Shutdown Procedure

  1. DO NOT, UNDER ANY CIRCUMSTANCES, pull the power cable or turn it off at the switch. This can corrupt the SD card and render it unusable.

  2. Every time you want to shut down your Pi, enter this command in the terminal: sudo shutdown now

  3. Press Enter to execute the shutdown command. You should see a series of text in the terminal announcing the shutdown.

Step 7: Knowing When It Is Safe to Switch Off

Like other computers, the Pi doesn't shut down instantly. Here is how you can tell when it's safe to turn it off at the wall or remove the plug.

  1. Your monitor screen turns off completely. The Acer I used showed a "No Signal" message.

  2. The LED is no longer green, leaving a red light behind. This means the Pi is powered but not fully on.

Conclusion

Congratulations, you've just set up a Raspberry Pi. Pat yourself on the back, give your Pi a pat on its back, and revel in the freedom of self-hosted tech.

You can stop reading if this is all you needed. Alternatively, you can find other guides on what to do with your brand new Pi friend.

Pi-Roject: Using a UPS with Your Pi

One of the risks of running a Pi 24/7 is a sudden loss of power, a tripped socket, a power cut, or someone accidentally kicking the cable. Without warning, this can corrupt your SD card, which as you know by now is catastrophic. The solution is a UPS HAT (Uninterruptible Power Supply Hardware Attached on Top).

This guide covers the Waveshare UPS HAT (B), which piggybacks onto your Pi via its GPIO pins and provides backup power from two 18650 lithium cells. Beyond just keeping the lights on briefly, we will set up a background service that monitors battery level and shuts the Pi down cleanly before the battery dies.

Once everything is in place, the service runs silently in the background. It checks battery level every 60 seconds, warns you when it drops below 15%, gives you 60 seconds to plug in the charger, and if you don't, shuts the Pi down safely on its own.

What You Will Need

Waveshare UPS HAT (B). The HAT itself. The 18650 batteries aren't included and must be sourced separately. Use official Waveshare batteries if possible, and don't mix old and new batteries or cells from different manufacturers.

2× 18650 Lithium batteries. These slot into the HAT and provide the backup power. Handle with care, as lithium batteries can be dangerous if mishandled. Mind the polarity markings (+ and −).

Barrel jack power adapter (5V recommended). The HAT is powered through a barrel jack rather than USB-C. This usually comes with the HAT.

Small Phillips screwdriver. For the mounting screws that keep the HAT attached to the Pi.

The monitor script. ups_monitor.py. You'll install this in Step 4.

Step 1: Physical Installation

The HAT connects to your Pi via pogo pins, small spring-loaded gold contacts that press against the Pi's GPIO pads. They look intimidating but are tougher than they appear and are designed for repeated connection and disconnection. Important: do this before your Pi is in its case. The case needs to come off entirely for the HAT to attach, learned this one the hard way.

  1. Insert the batteries first, before touching the Pi. Check the polarity markings on the HAT and slide both cells in flush.

  2. Remove the Pi from its case. If it won't budge, check the SD card is fully seated, as a partially inserted card can jam things up.

  3. Attach the HAT. Place it flat on your workspace, blue side up. Lower the Pi down onto it, lining up the GPIO header with the pogo pins. Press down firmly and steadily, think "firm handshake," not "crushing grip." Hold it steady while you screw down the mounting screws.

  4. Make sure the HAT's power switch is OFF, then plug in the barrel jack and flip it to ON. A red LED means the batteries are charging. Green means fully charged.

Step 2: SSH In and Enable I2C

I2C is the communication protocol that lets the Pi talk to the HAT's sensor (an INA219 chip). It's disabled by default and must be switched on before any monitoring software will work.

  1. SSH into your Pi as normal, then run: sudo raspi-config

  2. Navigate to 3 Interface Options → I5 I2C, select Yes, and reboot when prompted.

  3. After rebooting, verify the HAT is being detected: sudo i2cdetect -y 1

  4. You should see a grid with 42 appearing at row 40, column 2. That's the HAT's I2C address (0x42). If you see it, you're good to go.If 42 doesn't appear, double-check I2C is enabled and that the HAT is firmly seated. Unscrew it, realign it slightly, and press down more firmly before screwing back if the pogo pins aren't making contact.

  5. While you're at it, check the Python smbus library is installed: sudo apt update then sudo apt install -y python3-smbus

Step 3: (Optional) Test with Waveshare's Example Script

Waveshare provides a basic monitoring script that's useful for confirming everything is working before you set up the full service. You can skip this if you're confident, but it's a good sanity check.

  1. Install the extraction tool: sudo apt-get install p7zip

  2. Download the example script archive: wget https://files.waveshare.com/upload/4/4a/UPS_HAT_B.7z

  3. Extract it: 7zr x UPS_HAT_B.7z -r -o./

  4. Move into the extracted folder: cd UPS_HAT_B

  5. Run the script: python3 INA219.py

You should see readings like:

Load Voltage: 7.776 V
Current: 1.076000 A
Power: 2.416 W
Percent: 74.0%

Load Voltage is what the Pi is receiving from the HAT, a healthy range is 7.5–8.4V. Current will be positive if the batteries are charging and negative if they are actively supplying power. Press Ctrl+C to stop. Don't run this script and the monitor service simultaneously, as they both read the same sensor.

Step 4: Install the Monitor Script

Download ups_monitor.py and transfer it to your Pi.

  1. Transfer it with scp from your main machine: scp ups_monitor.py yourname@your.pi.ip.address:~/ups_monitor.py

  2. Open the script and find the line inside the notify_users() function containing your home directory path, which will look something like /home/yourusername/ups_notice.txt. Replace yourusername with whatever username you set during the Pi wizard.

  3. Adjust the three settings near the top of the file if needed:

    • CHECK_INTERVAL = 60, how often in seconds to read the battery sensor.
    • LOW_BATTERY_PERCENT = 15, the percentage at which the warning fires and the countdown begins.
    • SHUTDOWN_DELAY = 60, how many seconds you have to plug the charger back in before the Pi shuts itself down.

Steps 5 & 6: Install the Service

Copy the script into place and install the service that starts it on every boot.

  1. Create the directory and move the script into it: sudo mkdir -p /opt/ups_monitor, then sudo cp ~/ups_monitor.py /opt/ups_monitor/ups_monitor.py

  2. Make it executable: sudo chmod 755 /opt/ups_monitor/ups_monitor.py

  3. Create the log file: sudo touch /var/log/ups_monitor.log, then sudo chmod 644 /var/log/ups_monitor.log

  4. Run the script manually once to confirm it reads the sensor correctly: sudo python3 /opt/ups_monitor/ups_monitor.py. You should see output like Battery: 83.5% | Voltage: 8.00V. Press Ctrl+C once satisfied.

  5. The service file is embedded in the script's header comments. Follow those instructions to install it, then run: sudo systemctl enable ups-monitor.service, followed by sudo systemctl start ups-monitor.service

  6. Verify with sudo systemctl status ups-monitor.service and look for active (running). Your SD card is now protected.

Service won't start? Check logs with journalctl -u ups-monitor.service -n 50 and verify smbus is installed: python3 -c "import smbus; print('OK')". To watch the log live: tail -f /var/log/ups_monitor.log

How Warnings Work

Since the Pi runs headless, warnings come through two ways. If you're logged in via SSH, a broadcast message will appear directly in your terminal. If you aren't, the script writes to ~/ups_notice.txt, which you can check any time with cat ~/ups_notice.txt. If nobody is logged in at all, the Pi will still shut itself down safely before the power runs out, which is the whole point.

Useful Service Commands.

  • sudo systemctl status ups-monitor.service
  • sudo systemctl restart ups-monitor.service
  • sudo systemctl stop ups-monitor.service
  • journalctl -u ups-monitor.service -n 50

Conclusion

Congratulations, your Pi is now protected against sudden power loss. The monitor service runs quietly in the background, checking the battery every 60 seconds and giving you a safe, automatic shutdown if the power ever goes out while you're away. Your SD card, and everything on it, is a little safer for it.

Setting Up No-IP and WinACME

This gives your stack a stable hostname (e.g. helloworld.ddns.net) regardless of changes your home IP address might experience, and a real TLS certificate to go with it. If you have already done the IRC guide, you have both, so skip ahead to TLS Certificates.

  1. Go to https://www.noip.com and sign up for a free account. Once logged in, go to Dynamic DNS, No-IP Hostnames and create a new hostname such as helloworld.ddns.net. Write this down and treat it like a password.

  2. Download the No-IP DUC (Dynamic Update Client) from https://www.noip.com/download?page=win. This is a small background app that watches your public IP address and automatically updates No-IP whenever it changes. Without it, your hostname will point to the wrong IP after a router restart.

  1. Install the DUC, log in with your No-IP account credentials, and make sure your hostname is ticked. Set it to run on startup so it is always active in the background.

  2. Once the DUC is running, verify everything is working by looking up your hostname at https://www.nslookup.io. The A record should match your current public IP, which you can check at https://www.whatismyip.com.Note: No-IP's free tier requires you to confirm your hostname every 30 days, or they will delete it. Keep an eye on your inbox for their reminder emails.

Generating Certificates with WinACME

To use these services from outside your home network, you need a real TLS certificate. WinACME gets you a free one from Let's Encrypt, using your No-IP hostname to verify you control the domain.Before you start: make sure port 80 is forwarded on your router and opened in your Windows firewall. This is a temporary measure: WinACME needs to answer a challenge on this port to prove you control the domain.

  1. Download WinACME from https://www.win-acme.com. Extract the ZIP somewhere convenient, e.g. C:\Users\YourName\Downloads\win-acme\

  2. Open PowerShell as Administrator in the WinACME folder and run: ./wacs.exe

You will be walked through an interactive menu. Here is what to pick at each step:

  • Choose "Create certificate (full options)", not the simple IIS option.
  • For source, pick "Manual input" and enter your No-IP hostname, e.g. helloworld.ddns.net
  • For validation, pick "Self-hosted (HTTP-01)". WinACME will spin up a tiny temporary HTTP server on port 80 so Let's Encrypt can confirm you control the hostname.
  • Leave the private key type as the default (RSA).
  • For storage, pick "PEM encoded files". Choose a folder to save them to, e.g. C:\Users\yourname\Documents\Ergo\certs\
  • Accept the defaults for any remaining prompts and proceed.
  1. If everything executed correctly, WinACME will save PEM files to your chosen folder. Look for files ending in -chain.pem and -key.pem. You will reference these throughout this guide.

  2. You can remove the port 80 forwarding rule once the cert is issued.Note on renewal: Let's Encrypt certs expire after 90 days. WinACME installs a scheduled task to auto-renew them. If renewal fails (e.g. port 80 is not forwarded), WinACME will send a reminder email.

Setting Up Passwordless SSH (Windows to Pi)

This is needed so the cert copy script can run without a password prompt. Run on Windows as Administrator:

ssh-keygen -t rsa -b 4096
(hit Enter through all prompts, no passphrase)
type C:\Users\yourname\.ssh\id_rsa.pub | ssh yourname@192.168.1.132 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Enter the Pi password when prompted. Test it by running ssh yourname@192.168.1.132, it should connect with no password.

The Cert Copy Script

Download copy-certs-to-pi.bat and save it to C:\Users\yourname\Documents\. This copies the renewed certs to the Pi, restarts Ergo and reloads nginx. Add it as a post-renewal installation step in WinACME so it runs automatically after every renewal.

Gokapi: Self-Hosted File Sharing

Gokapi is a lightweight, self-hosted alternative to temporary file-sharing services like Catbox: upload a file, get a link, and have it expire automatically after a set time or download count.

A quick note on ports, since they come up constantly from here on: a port is just a numbered channel on your Pi. Different services each claim a different number, so incoming traffic gets routed to the right one. You can run as many services as you like on a single Pi and a single hostname, as long as they use different port numbers. Gokapi listens internally on port 53842, with nginx exposing it externally over HTTPS on port 8444.

Step 1: Downloading the Binary

SSH into your Pi first. All commands below run on the Pi.

  1. Go to /opt and create a folder for Gokapi: cd /opt, then sudo mkdir gokapi && sudo chown $(whoami):$(whoami) gokapi, then cd gokapi

  2. Query the GitHub API for the exact download URL:

    curl -s https://api.github.com/repos/Forceu/Gokapi/\
    releases/latest | grep "browser_download_url"
  3. This prints all available download URLs for the latest release. Find the one ending in linux-arm64.zip. The Pi 4B uses 64-bit ARM.

  4. Download the correct file (substitute the URL from above):

    wget [URL from step 3]
  5. Unzip, make executable and remove the archive (substitute your filename): unzip gokapi-*.zip, then chmod +x gokapi, then rm gokapi-*.zip

  6. Verify it runs: ./gokapi --version

Step 2: Running the Setup Wizard

Gokapi has a first-run setup wizard that runs in your browser. To access it from your Windows machine, you need to forward the port over SSH first.

  1. Open an SSH tunnel on your local machine (not the Pi): ssh -L 53842:localhost:53842 yourname@192.168.1.132. This tunnels port 53842 on the Pi through to your local machine so that localhost:53842 in your browser connects to Gokapi on the Pi.

  2. On the Pi, start Gokapi: cd /opt/gokapi, then ./gokapi

  3. In your browser, go to http://localhost:53842/setupThe setup wizard only appears on first run. If Gokapi has already been initialised (a data directory exists), visiting /setup will redirect you to the login page instead.

Work through each wizard page in order:

  1. Database. Leave Type as SQLite and Location as /data/gokapi.sqlite. This is a relative path: with WorkingDirectory=/opt/gokapi in the systemd service, the database lands at /opt/gokapi/data/gokapi.sqlite.

  2. Webserver 1/2. Make webserver only accessible on this machine: Yes (nginx handles the public-facing side). Use SSL: No (nginx handles TLS). Log IP address on download: your choice. Include filename in download URL: Yes.

  3. Webserver 2/2. Public Name: your choice. Port: leave as 53842. Public facing URL: https://helloworld.ddns.net:8444/ , using the port you plan to expose publicly, not 53842. Redirection URL for the index: leave as the GitHub page, or point it elsewhere.

  4. Storage. Leave as Local Storage.

  5. Encryption Level. Level 0 means that there's no encryption. This is fine for us, as nginx covers the encryption before anything goes through the Pi.Level 2 (end-to-end encryption) has a known Firefox compatibility issue where downloads fail. Check the Gokapi issue tracker for the current status before selecting it.

  6. Credentials. Set your admin username and password here.

After completing the setup wizard, Gokapi restarts and redirects your browser to the public URL. You'll get a connection error at this point. That's expected: Nginx isn't set up yet.The public-facing URL you entered is baked into every download link Gokapi generates. If it needs correcting, re-run the wizard or edit /opt/gokapi/data/config.json directly.

Step 3: Systemd Service

Running Gokapi manually in a terminal means it stops when you close the terminal or disconnect SSH, and doesn't restart after a Pi reboot. Once you've a systemd service, the problem solves itself.

Stop any manually running instance first. If Gokapi is still running from the setup wizard in Step 2, kill it before proceeding with sudo pkill gokapi. Both the manual process and the new service would try to bind port 53842, and the second one will fail to start.

Create the service file with sudo nano /etc/systemd/system/gokapi.service:

Download gokapi.service and paste its contents into the file. Replace yourname with your actual username. WorkingDirectory is important: Gokapi writes its data/ folder relative to the working directory, so it needs to point to /opt/gokapi.If the service fails to start after a reboot, check journalctl -u gokapi -n 50. The most common cause is WorkingDirectory being wrong or the binary having been moved.

Enable and start the service:

  1. sudo systemctl daemon-reload
  2. sudo systemctl enable gokapi
  3. sudo systemctl start gokapi
  4. sudo systemctl status gokapi . Look for Active: active (running) in the output, along with Gokapi's startup banner in the log lines

Step 4: Configuring Nginx

Nginx acts as a reverse proxy: it sits in front of Gokapi, handles the TLS certificate, and forwards requests through to Gokapi on port 53842 internally.

Check which ports are already in use before picking one with sudo ss -tlnp. In this setup, the following were already in use:

22     SSH
80     Nginx HTTP
8083   Calibre-Web (internal only)
8097   Ergo IRC HTTP/WebSocket
8443   Nginx HTTPS (Calibre-Web)
6697   Ergo IRC (TLS)

Port 8444 was the obvious pick, right next to 8443, which was already taken.

Create the nginx site config with sudo nano /etc/nginx/sites-available/gokapi:

Download gokapi-nginx and paste its contents into the config file, substituting your hostname and cert paths.

Two things here are Gokapi-specific; you won't need them for Calibre-Web. client_max_body_size 1024m raises nginx's default upload body limit of 1MB to 1GB. This is nginx's own restriction, not Gokapi's, and without it nginx will reject any upload larger than 1MB before the request reaches Gokapi. proxy_request_buffering off tells nginx not to buffer the entire upload in memory before forwarding it; without this, large uploads cause problems on a Pi.If nginx returns a 413 error on upload, client_max_body_size is missing or too low. If large uploads stall or fail outright, check that proxy_request_buffering off is present. Without it, nginx buffers the whole upload in memory before forwarding.

Verifying the setup. Once nginx has reloaded, visit https://helloworld.ddns.net:8444/admin. You should see the Gokapi login page with a padlock in the browser. If you see a certificate warning, check that fullchain.pem contains the full chain (your cert plus intermediate certs), not just your cert alone.

If the page doesn't load at all, check that Gokapi is running (sudo systemctl status gokapi) and that nginx reloaded successfully. Port forwarding isn't set up until Step 5. For now, test from inside your network using the Pi's local IP and port 8444 directly.

Enable the site and reload nginx:

  1. Create the symlink in sites-enabled: sudo ln -s /etc/nginx/sites-available/gokapi /etc/nginx/sites-enabled/
  2. Test the config before reloading. Always do this: sudo nginx -t
  3. Reload if the test passes: sudo systemctl reload nginx

If nginx -t returns an error, don't reload. Read the error message carefully: it'll give you the exact line with the problem. Common causes are missing semicolons, wrong file paths, or a typo in server_name. Fix it before you reload; one bad nginx configuration will tank all the web services that rely on it.

You'll want to see:

nginx: configuration file /etc/nginx/nginx.conf \
  syntax is ok
nginx: configuration file /etc/nginx/nginx.conf \
  test is successful

Step 5: Port Forwarding

For Gokapi to be accessible from outside your home network, your router needs to forward external traffic on port 8444 to the Pi.

  1. Log into your router admin panel (commonly at 192.168.1.1 or 192.168.1.254).

  2. Find the Port Forwarding section, which may be under Firewall, NAT, or Advanced Settings.

  3. Create a new rule:

Device/Internal IP: your Pi's local IP
External port: 8444
Internal port: 8444
Protocol: TCP
  1. Save the rule.

  2. Test by visiting https://helloworld.ddns.net:8444/admin in your browser from a device on a different network (a mobile phone on 4G works well).Port 53842, the port Gokapi itself listens on, doesn't need a forwarding rule. Nginx on port 8444 is the only public entry point.

Step 6: Creating a Second User

If you want to give a friend upload access, create an account for them rather than sharing the admin credentials.

  1. Log into Gokapi at https://helloworld.ddns.net:8444/admin

  2. Click Users in the navigation bar.

  3. Click the add user button (the circle icon in the top right of the Users panel).

  4. Fill in a username and set their permissions.

  5. To set their password: click the arrow/login button on their row. This generates a one-time login link. Send it to your friend; they use it to set their own password on first login.

That way in the event of a breach, you can delete it without torching your admin privileges or starting over again.

Gokapi runs a cleanup routine every hour deleting expired files. Once a file expires, you can confirm it was removed at https://helloworld.ddns.net:8444/logs.To check disk usage: du -sh /opt/gokapi/data/. This directory should stay small since files delete after expiry. If it grows, check for uploads with a very long or no expiry set.

Gokapi is now running as a persistent service, secured behind nginx with a real TLS certificate, and accessible over HTTPS. Files expire automatically by time or download count. Accounts keep uploads restricted to people you choose.

Calibre-Web: Self-Hosted Library

Calibre-Web is a self-hosted web frontend for a Calibre ebook library: browse, read, and download books from any device, anywhere.

Step 1: Installing Calibre-Web

  1. Install Python venv support: sudo apt update && sudo apt install -y python3-pip python3-venv
  2. Create the virtual environment: python3 -m venv ~/calibre-web-envA venv is an isolated Python installation, a sandbox just for Calibre-Web that prevents its dependencies from conflicting with system packages.
  3. Activate it: source ~/calibre-web-env/bin/activate
  4. Install Calibre-Web: pip install calibreweb
  5. Create your books directory: mkdir ~/books
  6. Start Calibre-Web: cpsThis occupies the terminal, so open a second SSH session for everything else. Commands typed here appear in the log but don't run, and remain visible. Once Step 5's service is in place, this goes away.

First-Run Setup.

  1. Go to http://YOUR_PI_IP:8083. Log in with admin / admin123 and change the password immediately.
  2. Set the library path to /home/yourname/books.
  3. If you get New db location is invalid, please enter valid path: the database doesn't exist yet. Do Step 2 first.

Step 2: The Calibre Database

Calibre-Web is a frontend: it reads from a Calibre library database (metadata.db) that has to exist before you can use it. You'll create it here using calibredb, the CLI tool that comes with the Calibre package. The full Calibre GUI won't run on a headless Pi, but you don't need it.

  1. Install the Calibre CLI tools: sudo apt install -y calibreThis is a large package, so expect 5–10 minutes on a Pi 4B. Deprecation warnings from piwheels during subsequent pip operations are harmless.

  2. Create the library database: calibredb --with-library ~/books list

    This creates metadata.db inside ~/books and prints an empty table. Empty output is correct; no books have been added yet. Only after this will Calibre-Web accept /home/yourname/books as a valid library path.Troubleshooting: if calibredb returns "No such file or directory", check that ~/books exists. Run mkdir ~/books first if needed.

Step 3: Adding Books

  1. Copy PDFs to the Pi using SCP (Secure Copy Protocol). It piggybacks on your SSH connection to transfer files directly from your Windows machine to the Pi, with no extra software needed. Run it from a Windows Command Prompt, not from inside an SSH session:Open a new Command Prompt window for this, not an SSH session. On first connection, type yes to verify the Pi's fingerprint. Prefer FileZilla or WinSCP if you want a GUI (SFTP, port 22).

    Single file: scp "C:\Users\NAME\Documents\book.pdf" yourname@192.168.x.x:/home/yourname/books/Books/

    Folder: scp -r "C:\Users\NAME\Documents\Books" yourname@192.168.x.x:/home/yourname/books/This copies the folder itself into the destination, giving /home/yourname/books/Books/yourfiles.pdf, which is correct for the calibredb add command below.

  2. Register the books from a fresh terminal (not the one running cps):

    calibredb add -r /home/yourname/books/Books --library-path /home/yourname/books

    Running this again later is fine; it'll skip anything you've already imported.If books you transferred are missing in Calibre-Web, they were placed in the folder but never registered in metadata.db. Run calibredb add -r to import them. Cover images are pulled automatically from PDF metadata.

Understanding the Error Output. When you run calibredb add, you'll see a rapid scroll of what look like errors: Syntax Errors, ValueErrors, pdfinfo failures. These come from Calibre's PDF parser trying to read internal metadata that many PDFs, simply don't have, especially old or scanned ones. Terminal errors tend to come fast and flat like this. While it looks bad, it’s doing fine and still uploading your texts.If the command ends with "Added book ids:" followed by nothing, all files were detected as duplicates. This is expected if you run the command twice on the same folder.

The line that matters is at the very end: Added book ids: 1, 2, 3, 4, ... Count the IDs to confirm how many books were imported.

Duplicate Detection. Running calibredb add twice on the same folder is safe; duplicates are detected by title and author and skipped with a note rather than added twice.

Adding More Books Later. SCP new PDFs to ~/books/Books/ and repeat step 2. Already-imported books are skipped automatically, no restart needed.calibredb add -r /home/yourname/books/Books --library-path /home/yourname/books

Step 4: HTTPS with Nginx Reverse Proxy

This step uses nginx as a reverse proxy, the same pattern as in the Gokapi guide, just with different ports (8443 and 8083 instead of 8444 and 53842). If you set up Gokapi first, this will look familiar. If nginx is new to you, see Step 4: Configuring Nginx in the Gokapi section before continuing here.

Install Nginx: sudo apt install -y nginx

Create the Site Config with sudo nano /etc/nginx/sites-available/calibre-web. Download calibre-web-nginx and paste its contents, substituting your hostname and cert paths.

Enable the Site.

  1. Create the symlink: sudo ln -s /etc/nginx/sites-available/calibre-web /etc/nginx/sites-enabled/
  2. Test the config before reloading, always: sudo nginx -t. If it returns "syntax is ok" and "test is successful", it's safe to reload. If there's a syntax error, it'll tell you exactly which line. Fix it before reloading - a broken nginx config can take down all your web services.
  3. Reload nginx: sudo systemctl reload nginx

reload applies config changes without dropping existing connections. Use reload for config changes, not restart.

Verifying the Cert is Working. Visit https://helloworld.ddns.net:8443 in a browser. You should see a padlock icon and no security warnings. If you see a certificate warning, check that fullchain.pem contains the full chain - your cert plus intermediate certs - not just your cert alone.A certificate warning showing up later usually means the cert has expired or the renewal script didn't run. Check expiry with openssl x509 -enddate -noout -in /home/yourname/ergo/certs/fullchain.pem and reload nginx after any cert update.

Port Forwarding for Calibre-Web. For Calibre-Web to be accessible from outside your home network, your router needs to forward external traffic on port 8443 to the Pi.

  1. Log into your router admin panel.

  2. Find the Port Forwarding section (may be under Firewall, NAT, or Advanced Settings).

  3. Create a new rule with these settings:

Device/Internal IP: your Pi's local IP
External port: 8443
Internal port: 8443
Protocol: TCP
  1. Save the rule.

  2. Test by visiting https://helloworld.ddns.net:8443 in your browser.

If the page doesn't load, check that Calibre-Web is running (sudo systemctl status calibre-web) and that nginx reloaded successfully. Also double-check that the port in your router rule matches the one in your nginx config.Note: your Pi's local IP is assigned via DHCP and can change after a reboot, breaking your port forwarding rules. Set a DHCP reservation (sometimes called static DHCP or IP binding) in your router's admin panel to permanently assign the same IP to your Pi's MAC address.

Step 5: Running as a Systemd Service

If cps is still running manually, stop it first with Ctrl+C, as both instances would try to bind port 8083 and the second will fail to start.

Create the service file with sudo nano /etc/systemd/system/calibre-web.service:

Download calibre-web.service and paste its contents into the file. Replace yourname with your actual username. The ExecStart path points directly into the venv, so no manual activation is needed.If the service fails to start, check journalctl -u calibre-web -n 50. The most common cause is a path error in the service file or the venv having been moved. To update Calibre-Web later: activate the venv, run pip install --upgrade calibreweb, then sudo systemctl restart calibre-web.

  1. sudo systemctl enable calibre-web
  2. sudo systemctl start calibre-web
  3. Verify: sudo systemctl status calibre-web . Look for Active: active (running).

Step 6: Security

  1. Change your password immediately. The default admin / admin123 is publicly documented.

    Admin → Users → admin → set a new password.

  2. Disable Public Registration.

    Admin → Configuration → Feature Configuration → Allow Registration = OFF.

  3. Disable Anonymous Browsing.

    Admin → Configuration → Allow Anonymous Browsing = OFF.

  4. When creating accounts for friends, give them the permissions they need and ensure they're on HTTPS only.Nginx proxies to localhost:8083 without 8083 needing to be publicly reachable at all.

Conclusion

Congratulations, you've just set up Calibre-Web. It's now running as a persistent service behind nginx with a real TLS certificate, reachable over HTTPS by anyone you've added. calibredb manages the books and picks up new additions live, no restart needed.