Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
This guide installs Gogs on Ubuntu 24.04 as a dedicated, unprivileged service, configures it to start with systemd, and puts Nginx and HTTPS in front of it. It uses SQLite for the simplest small deployment; PostgreSQL is an option when the service needs stronger database operations or more concurrent use. The official Gogs releases page showed v0.14.3, released June 7, 2026, when checked August 18, 2026; check the official release page before installing or upgrading.
What you will install
Gogs is a self-hosted Git service. The steps below target Ubuntu Server 24.04 and use the official pre-built Linux binary, a systemd unit, SQLite, and Nginx as a reverse proxy. Gogs listens only on the local loopback interface; Nginx handles public web traffic on ports 80 and 443. This keeps port 3000 off the public interface.
The commands use the AMD64 release asset. For an ARM64 server, use the corresponding ARM64 archive instead. Gogs supports SQLite 3, PostgreSQL 9.6 or newer, and MySQL 5.7 or newer; Git 1.8.3 or newer is required. An SSH server is needed for Git-over-SSH, though Gogs can also run its own built-in SSH server. See the official installation requirements.
Before you begin
- A fresh Ubuntu 24.04 server and a sudo-enabled administrative account.
- A working SSH connection for server administration.
- A domain name and DNS A or AAAA record pointing to the server if you want HTTPS at a friendly address.
- Disk space for repositories, attachments, logs, and backups. Requirements vary with repository size and usage; no single small memory figure guarantees adequate production capacity.
Gogs can also be installed with Docker or from source, but this procedure uses the binary because it fits a conventional Ubuntu and systemd setup. Docker’s security depends on the image, permissions, exposed ports, and update practices; it is not automatically safer. Gogs documents both installation approaches at gogs.io.
#1 Best Overall
Install Ubuntu packages
sudo apt update
sudo apt upgrade -y
sudo apt install -y
git
curl
ca-certificates
tar
sqlite3
openssh-server
Create a dedicated Gogs account
Do not run the service as root. Create a system account named git and directories for the application and its persistent data:
sudo adduser
--system
--shell /bin/bash
--gecos 'Gogs service account'
--group
--disabled-password
--home /home/git
git
sudo mkdir -p /home/git/gogs
sudo mkdir -p /var/lib/gogs/{custom,data,log,repositories}
sudo chown -R git:git /home/git
sudo chmod 750 /home/git
The service account needs write access to its configuration, database, repositories, data, and logs. Keeping persistent data under /var/lib/gogs makes it easier to identify and back up.
Download and verify the Gogs binary
For a 64-bit Intel or AMD server, download the pinned v0.14.3 release and verify its SHA-256 checksum before extracting it:
cd /tmp
curl -LO https://github.com/gogs/gogs/releases/download/v0.14.3/gogs_v0.14.3_linux_amd64.tar.gz
echo "c27fbd8337ebd661929389f5237bf601e09958d514835c99fad3b904c63bedb2 gogs_v0.14.3_linux_amd64.tar.gz"
| sha256sum -c -
The expected result is gogs_v0.14.3_linux_amd64.tar.gz: OK. For ARM64, substitute gogs_v0.14.3_linux_arm64.tar.gz and verify it against the checksum shown for that asset on the official release page; do not reuse the AMD64 checksum.
sudo tar -xzf gogs_v0.14.3_linux_amd64.tar.gz
-C /home/git
--strip-components=1
sudo chown -R git:git /home/git/gogs
sudo chmod 750 /home/git/gogs
sudo chmod +x /home/git/gogs/gogs
Configure SQLite and the public URL
Gogs reads custom settings from /home/git/gogs/custom/conf/app.ini. Its configuration file overlays the shipped defaults, so you can set only the values that need to differ. Create the directory and file as the service account:
sudo -u git mkdir -p /home/git/gogs/custom/conf
sudo -u git nano /home/git/gogs/custom/conf/app.ini
Use this starting configuration, replacing the example domain with your own. It uses an absolute SQLite path so the service does not silently create or open a different database because of its working directory.
RUN_MODE = prod
[database]
DB_TYPE = sqlite3
PATH = /var/lib/gogs/data/gogs.db
[server]
DOMAIN = gogs.example.com
HTTP_ADDR = 127.0.0.1
HTTP_PORT = 3000
EXTERNAL_URL = https://gogs.example.com/
DISABLE_SSH = false
START_SSH_SERVER = false
SSH_PORT = 22
[repository]
ROOT = /var/lib/gogs/repositories
[log]
MODE = file
LEVEL = Info
ROOT_PATH = /var/lib/gogs/log
[security]
INSTALL_LOCK = false
The reverse-proxy guidance uses EXTERNAL_URL for the public address. Keep it set to the HTTPS URL users will open, while Nginx connects to Gogs over local HTTP. If deploying beneath a URL subpath rather than at the domain root, follow the path-specific configuration guidance in Gogs’ reverse-proxy documentation rather than assuming this root-domain configuration will work unchanged.
Free tools Windows power users keep installed
One-click scans. No signup required.
Run Gogs once and check the installer
Start Gogs manually under the service account to catch basic configuration and permission errors before creating the service:
sudo -u git
HOME=/home/git
/home/git/gogs/gogs web
From another shell on the server, check that the local web listener responds:
Rank #2
curl -I http://127.0.0.1:3000
For a temporary direct test from your browser, open http://SERVER_IP:3000/install only if the server firewall allows access. A safer option is an SSH tunnel from your workstation:
ssh -L 3000:127.0.0.1:3000 user@SERVER_IP
Then visit http://127.0.0.1:3000/install on that workstation. Stop the foreground process with Ctrl+C after confirming it starts. The official binary launch command is gogs web; see Gogs installation documentation.
Recommended Free Tools
Run Gogs with systemd
Create a service unit that sets the account, home directory, and working directory explicitly. These settings avoid differences between an interactive shell and systemd:
sudo tee /etc/systemd/system/gogs.service >/dev/null <<'EOF'
[Unit]
Description=Gogs self-hosted Git service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/home/git/gogs
Environment=USER=git
Environment=HOME=/home/git
ExecStart=/home/git/gogs/gogs web
Restart=always
RestartSec=2s
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
Enable and start it, then check its state and logs:
sudo systemctl daemon-reload
sudo systemctl enable --now gogs
sudo systemctl status gogs --no-pager -l
sudo journalctl -u gogs -b --no-pager
The unit follows Gogs’ documented systemd approach of running as git with gogs web and automatic restarts. The official guidance also covers service status and journal checks: Run Gogs as a service.
Common operational commands:
sudo systemctl restart gogs
sudo systemctl stop gogs
sudo systemctl disable gogs
sudo journalctl -fu gogs
Put Nginx in front of Gogs
Install and start Nginx:
sudo apt install -y nginx
sudo systemctl enable --now nginx
Create /etc/nginx/sites-available/gogs and use this HTTP reverse-proxy configuration:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsserver {
listen 80;
listen [::]:80;
server_name gogs.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
Use 127.0.0.1 for the upstream rather than localhost; name resolution can select IPv6 and cause connection delays or failures. Gogs discusses that case in its troubleshooting guide.
sudo ln -s /etc/nginx/sites-available/gogs
/etc/nginx/sites-enabled/gogs
sudo nginx -t
sudo systemctl reload nginx
Once Nginx is working, allow SSH and web traffic through UFW, not public access to Gogs’ backend port:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status verbose
Confirm the cloud provider’s firewall, if any, also allows inbound ports 80 and 443. Gogs’ reverse-proxy guide describes forwarding public requests to port 3000.
Rank #3
Enable HTTPS with Certbot
Before requesting a certificate, make sure the domain resolves to this server and inbound HTTP and HTTPS are reachable. Install Certbot’s Nginx integration and request a certificate:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d gogs.example.com
Follow the prompts to enable HTTPS, then check that automatic renewal can complete:
sudo certbot renew --dry-run
Keep the public URL in app.ini as https://gogs.example.com/. TLS terminates at Nginx, while Nginx and Gogs communicate over local HTTP; the forwarded X-Forwarded-Proto header indicates the original scheme. These are the documented reverse-proxy and Certbot patterns in Gogs’ reverse-proxy guidance.
Complete the Gogs web installer
Open https://gogs.example.com/install. Check each installer field against the configuration and intended deployment:
- Database: choose SQLite3 and the absolute path
/var/lib/gogs/data/gogs.dbfor the small single-server setup. - Repository root: use
/var/lib/gogs/repositories. - Domain and application URL: use
gogs.example.comandhttps://gogs.example.com/, including the trailing slash in the public URL. - SSH: choose system OpenSSH or Gogs’ built-in SSH server deliberately. The sample configuration uses system OpenSSH rather than starting Gogs’ server.
- Administrator: create a unique account with a strong, non-reused password. Configure who may register accounts according to your intended audience.
- Site title: enter a name appropriate for your organization or personal instance.
After successful setup, edit /home/git/gogs/custom/conf/app.ini and set INSTALL_LOCK = true under [security], then restart the service with sudo systemctl restart gogs. Configure mail delivery in Gogs if you need email notifications or account-related messages; settings depend on your mail provider, so use the provider’s SMTP host, port, authentication, and TLS requirements rather than guessing values.
Choose system SSH or Gogs’ built-in SSH
The sample uses the system SSH service: DISABLE_SSH = false and START_SSH_SERVER = false. Users connect on port 22, and Ubuntu’s OpenSSH handles incoming connections. If you choose Gogs’ built-in SSH server instead, configure its listening port, permit that port through firewalls, and use the clone URL Gogs displays for that repository. Do not change SSH settings blindly on a remote server; preserve your administrative SSH access.
Copy the exact SSH clone URL from the repository page because the hostname, username, and port reflect your chosen mode. A typical system-SSH URL may resemble:
git clone ssh://[email protected]:22/USERNAME/REPOSITORY.git
HTTPS cloning and pushing are separate from SSH configuration and can be tested using the HTTPS URL displayed by Gogs.
Use PostgreSQL instead of SQLite when appropriate
SQLite keeps a small single-server installation straightforward and may suit a personal instance, homelab, or low-concurrency team. PostgreSQL is a better fit when database operations are business-critical, usage is more concurrent, or you already operate PostgreSQL backups and monitoring. This choice does not remove the need to back up repositories and Gogs configuration.
Rank #4
Install PostgreSQL and start its service:
sudo apt install -y postgresql
sudo systemctl enable --now postgresql
Create a database role and database. Replace the example password with a long random secret; avoid leaving a real password in shell history or published configuration:
sudo -u postgres psql
CREATE USER gogs WITH PASSWORD 'REPLACE_WITH_A_LONG_RANDOM_PASSWORD';
CREATE DATABASE gogs OWNER gogs ENCODING 'UTF8';
q
Initialize the database before selecting PostgreSQL in Gogs, as described in the official installation documentation. Then set the database section of app.ini:
[database]
DB_TYPE = postgres
HOST = 127.0.0.1:5432
NAME = gogs
USER = gogs
PASSWORD = REPLACE_WITH_A_LONG_RANDOM_PASSWORD
SSL_MODE = disable
SSL_MODE = disable is appropriate only when PostgreSQL and Gogs are on the same trusted host or protected private network. For a remote database, use TLS and the appropriate PostgreSQL certificate settings. Do not expose PostgreSQL publicly without a specific operational reason.
Verify the deployment
Check that Gogs is enabled, running, and reachable locally, and that Nginx configuration and certificate renewal are valid:
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →systemctl is-enabled gogs
systemctl is-active gogs
curl -I http://127.0.0.1:3000
sudo nginx -t
sudo certbot renew --dry-run
- Sign in through the HTTPS address and create a test repository.
- Clone over HTTPS, push a commit, and browse the repository in the web interface.
- If SSH is enabled, test an SSH clone using the exact URL shown by Gogs.
- Check registration policy and email delivery if configured.
- Restart Gogs, then reboot the server and confirm the service and site return.
Back up data and plan upgrades
A recoverable Gogs backup must include the database, repositories, custom configuration, and other persistent data such as attachments. Preserve /home/git/gogs/custom/, /var/lib/gogs/data/, /var/lib/gogs/repositories/, and /var/lib/gogs/log/. The most important configuration file is /home/git/gogs/custom/conf/app.ini; protect it because it can contain credentials and security settings.
Back up SQLite
For a simple file-level backup, stop Gogs so the database is not changing while it is archived:
sudo systemctl stop gogs
sudo tar -czf /var/backups/gogs-$(date +%F).tar.gz
/home/git/gogs/custom
/var/lib/gogs
sudo systemctl start gogs
Store backups somewhere other than the same server if you need protection against disk loss, and periodically restore one to a separate test location. Creating an archive alone does not prove the backup can be restored.
Back up PostgreSQL
sudo -u postgres pg_dump -Fc gogs
> /var/backups/gogs-$(date +%F).dump
Back up the repositories and Gogs configuration separately as well. Test database and file restoration together before relying on the backup plan.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Upgrade without overwriting persistent data
- Back up the database, repository data, and configuration.
- Read the release notes for the target version, including migration and security notes.
- Stop the Gogs service.
- Replace the application binary or files required by the release while preserving
custom/, repositories, database files, and other persistent data. - Start Gogs and inspect
sudo journalctl -u gogs -b --no-pager. - Test login, repository browsing, clone and push, webhooks, and email where used.
Monitor the official releases page for updates. Release notes include security changes affecting reverse-proxy authentication trust and webhook SSRF protections. Do not enable proxy-based authentication headers unless trusted proxy addresses are restricted and correctly configured.
Best Value
Troubleshoot common problems
systemd cannot start Gogs
Inspect the journal, then check the binary and try the same executable under the service account:
sudo journalctl -u gogs -b --no-pager
ls -l /home/git/gogs/gogs
sudo -u git /home/git/gogs/gogs web
Common causes include a binary for the wrong CPU architecture, missing execute permission, a bad working directory, incorrect ownership, malformed app.ini, or another process already using the configured port. Explicit HOME and WorkingDirectory values in the service unit help avoid shell-versus-systemd differences; see Gogs’ systemd guidance.
Port 3000 is occupied
sudo ss -ltnp | grep ':3000'
Stop the conflicting service or change Gogs and Nginx to the same unused port, for example:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute[server]
HTTP_PORT = 3001
proxy_pass http://127.0.0.1:3001;
Then restart Gogs and validate and reload Nginx:
sudo systemctl restart gogs
sudo nginx -t
sudo systemctl reload nginx
Nginx returns 502 Bad Gateway
Check that Gogs is running and listening locally, then inspect the Nginx error log:
sudo systemctl status gogs
sudo ss -ltnp | grep ':3000'
sudo tail -n 100 /var/log/nginx/error.log
Confirm that Nginx’s upstream port matches HTTP_PORT and that the upstream is 127.0.0.1. Gogs documents the localhost/IPv6 issue in its troubleshooting notes.
The installer cannot write files
Check that the service account owns the application and data directories and can write to the database and repository paths:
sudo chown -R git:git /home/git/gogs /var/lib/gogs
sudo -u git test -w /var/lib/gogs/data && echo writable
sudo -u git test -w /var/lib/gogs/repositories && echo writable
Gogs opens the wrong SQLite database
Set the database path to an absolute location rather than a relative path:
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →[database]
DB_TYPE = sqlite3
PATH = /var/lib/gogs/data/gogs.db
Relative paths can resolve differently when Gogs is started manually and under systemd; the official troubleshooting guide identifies this as a cause of apparently missing data.
HTTPS redirects loop
- Confirm Nginx sends
X-Forwarded-Proto. - Set Gogs’ public URL to the exact HTTPS domain users open.
- Keep the connection from Nginx to Gogs on local HTTP if Nginx terminates TLS.
- Check that Nginx’s redirects and the configured domain match the browser URL.
Gogs’ reverse-proxy documentation describes this TLS-termination arrangement.
Large HTTP pushes fail with 413
Nginx may reject a request that exceeds its body-size limit. Add a suitable limit inside the relevant server block, for example:
client_max_body_size 50m;
sudo nginx -t
sudo systemctl reload nginx
Choose a limit that fits your use rather than treating 50 MB as a universal requirement. Gogs’ reverse-proxy guide discusses Nginx request-size limits.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →When another Git service may fit better
Gogs suits administrators who want a lightweight, self-hosted Git service and are prepared to maintain the application, database, backups, and server. Forgejo is a community-oriented Gitea-derived forge; Gitea is another lightweight self-hosted option. GitLab provides a broader DevOps platform but brings more operational complexity and resource needs. Hosted services such as GitHub, GitLab.com, or Bitbucket Cloud avoid server administration, in exchange for relying on a provider’s policies and hosted-plan limits. Choose based on the features and maintenance responsibility you actually need, not on a claim that one option is best for every team.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

