# Self-hosting with Gitea

- [Gitea](https://gitea.io/en-us/)
	- [Gitea Config Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/)
- [Updating Gitea](./gitea-update.md)

## Vultr Gitea instance with PostgreSQL

The following is example configuration for a low-cost Vultr instance that can easily run Gitea with PostgreSQL used for data storage.

1. Cloud Compute
2. intel Regular Performance
3. Chicago United States
4. Debian 11 x64
5. 25 GB SSD for $5/month with 1 vCPU, 1 GB Memory, 1 TB Bandwidth
6. Disable Auto Backups
7. Enable IPv6

- [Referral link](https://www.vultr.com/?ref=9110044)
- Non-referral link: [Cloud Compute](https://www.vultr.com/products/cloud-compute/)

### Initial setups
1. Create a new non-root user
	- `adduser <new-user>`
	- `usermod -aG sudo <new-user>`
	- `exit`
2. Initial updates
	1. `sudo apt update`
	2. `sudo apt upgrade` if needed (wasn't required)
	3. `sudo apt autoremove` to remove ~310 MB of packages
3. Install required packages
	1. `sudo apt install postgresql` (version 13)
	2. `sudo apt install git` (version 2.30.2)
	3. `sudo systemctl start postgresql`
	4. `sudo systemctl enable postgresql`
	5. `sudo systemctl status postgresql`

### PostgreSQL Setup
1. `sudo vim /etc/postgresql/13/main/postgresql.conf`
	- Under Connections and Authentication, update `password_encryption` from `md5` to `scram-sha-256` and uncomment.
2. `sudo vim /etc/postgresql/13/main/pg_hba.conf`
	- Update all `md5` instances to `scram-sha-256`.
3. `sudo service postgresql restart` (restart service / reload config)
4. `sudo -i -u postgres`
5. `psql`
6. `CREATE ROLE gitea WITH LOGIN PASSWORD 'TODO-SET-PASSWORD';`
	- Alter it: `ALTER ROLE gitea WITH PASSWORD 'TODO-SET-NEW-PASSWORD';`
7. `CREATE DATABASE giteadb WITH OWNER gitea TEMPLATE template0 ENCODING UTF8 LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8';`
8. `quit` (psql)
9. `exit` (postgres user)
10. `sudo vim /etc/postgresql/13/main/pg_hba.conf`
	- Add a new line with `local    giteadb    gitea         scram-sha-256` for local access.
11. `sudo service postgresql restart`
12. `psql -U gitea -d giteadb` to verify access.

### Install Gitea (1.16.8 at the time of writing)
1. `uname -mrs` to confirm amd64.
2. Get link from https://dl.gitea.io/gitea/
	- https://dl.gitea.io/gitea/1.16.8/gitea-1.16.8-linux-amd64
3. `wget -O gitea https://dl.gitea.io/gitea/1.16.8/gitea-1.16.8-linux-amd64`
4. `chmod +x gitea`
5. `sudo mv gitea /usr/local/bin/gitea`
6. `sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git`
7. Setup directory structure:
	- `sudo mkdir -p /var/lib/gitea/{custom,data,log}`
	- `sudo chown -R git:git /var/lib/gitea/`
	- `sudo chmod -R 750 /var/lib/gitea/`
	- `sudo mkdir /etc/gitea`
	- `sudo chown root:git /etc/gitea`
	- `sudo chmod 770 /etc/gitea`
8. `sudo wget https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/systemd/gitea.service -P /etc/systemd/system/`
9. `sudo nano /etc/systemd/system/gitea.service`
	- Uncomment `Wants=postgresql.service` and `After=postgresql.service` lines.
10. `sudo systemctl daemon-reload`
11. `sudo systemctl enable --now gitea`
12. `sudo systemctl status gitea`
13. `sudo ufw allow 3000/tcp`

### Configure Gitea
1. http://<ip>:3000
2. Select PostgreSQL as Database Type
3. Set Password.
4. Change Database Name to giteadb
5. Update Gitea Base URL to http://<ip>:3000/
6. Create a new administrator account.
7. Once setup, logout and log back in with new account.
8. `sudo vim /etc/gitea/app.ini` if you want to update after the fact.

### Lockdown Gitea
This locks down Gitea so that only signed in users can access the site, and registration isn't available.
1. `sudo vim /etc/gitea/app.ini`
2. `[service]`
	- DISABLE_REGISTRATION = true
	- REQUIRE_SIGNIN_VIEW = true
3. `sudo service gitea restart`
4. `sudo chmod 750 /etc/gitea`
5. `sudo chmod 640 /etc/gitea/app.ini`

### Nginx
1. Setup a new (sub)domain to point to the server.
2. Should be able to access http://<domain>:3000.
3. `sudo apt install nginx`
4. `sudo ufw allow 'Nginx HTTP'`
5. `sudo ufw status`
6. `systemctl status nginx`
7. `sudo nano /etc/nginx/nginx.conf`
```
server {
    listen 80;
    server_name git.example.com;

    location / {
        proxy_pass http://localhost: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;
    }
}
```
8. `sudo nginx -t` to verify configuration changes
9. `sudo systemctl restart nginx`
10. Custom domain, port 80, should now work.

## Certbot / SSL
1. `sudo apt install certbot python3-certbot-nginx`
2. `sudo ufw allow 'Nginx Full'`
3. `sudo ufw delete allow 'Nginx HTTP'`
4. `sudo ufw status`
5. `sudo certbot --nginx -d git.ebacher-skemp.com` (or whatever custom domain was setup)
6. `sudo systemctl status certbot.timer` (verify Certbot will run again automatically)
7. `sudo certbot renew --dry-run` (fake a cert renewal to make sure it picks it up)
8. https://<custom-domain> should work for Gitea access, and http should redirect
9. `sudo nano /etc/gitea/app.ini`
	- Update server > ROOT_URL
	- Also needed to add a repository > DEFAULT_BRANCH = main
10. `sudo service gitea restart`
11. `sudo ufw delete allow 3000/tcp` (no longer allow external access via 3000)

### Other Customizations
- In my.vultr.com, add the following tags to the server instance (so I know core functionality):
	- gitea
	- postgresql
	- nginx
	- certbot
- `sudo apt install htop` (prettier top)
- `sudo vim /etc/gitea/app.ini`
	- `repository` > `ENABLE_PUSH_CREATE_USER = true`
	- `repository` > `ENABLE_PUSH_CREATE_ORG = true`
	- `cron.repo_health_check` > `TIMEOUT = 90s`
	- `service` > `REQUIRE_SIGNIN_VIEW = false` (updated 4/2023)
	- `server` > `SSH_DOMAIN = git.domain.com` (updated 8/2023)
		- `DOMAIN` is fine as `localhost` since `ROOT_URL` is set.
	- `server` > `LANDING_PAGE = explore` (updated 12/2023)
- `sudo nano /etc/nginx/nginx.conf`
	- Add `client_max_body_size 100M;` to gitea server section (to allow for larger files)
	- `sudo nginx -t`
	- `sudo systemctl restart nginx`

### Regular backups
On the server:
```bash
sudo systemctl stop gitea
sudo su - git
gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -t /tmp
ls -l --block-size=M
rm <old-backup-file>
# Grant everyone read access to the backup file.
chmod a=r <backup-file>
exit
sudo systemctl restart gitea
```

On your local machine:
```bash
# Copy the file locally.
scp <user>@<remote_ip>:/home/git/<backup-file> d:\
```

### SMTP setup with Fastmail
1. `sudo vim /etc/gitea/app.ini`
2. Update `[mailer]` per the below.
3. `sudo systemctl restart gitea`
4. Send a test email from Gitea's `/admin/config`.

```
[mailer]
ENABLED        = true
FROM           = gitea@mydomain.com
SMTP_ADDR      = smtp.fastmail.com
SMTP_PORT      = 465
USER           = `your.email@fastmail.com`
PASSWD         = `password`
```

`USER` must be your primary Fastmail email. `PASSWD` is an application password. `FROM` can be your primary or an alias email.

### Enable code search
1. `sudo vim /etc/gitea/app.ini`
2. Add `[indexer]` per the below.
3. `sudo systemctl restart gitea`
4. After some time, run `sudo du -sh /var/lib/gitea/indexers` to check index size.
	- `sudo ls -lhR /var/lib/gitea/indexers/repos.bleve` will list file sizes and dates.

```
[indexer]
REPO_INDEXER_ENABLED = true
REPO_INDEXER_PATH = indexers/repos.bleve
MAX_FILE_SIZE = 1048576
REPO_INDEXER_INCLUDE = **.bat,**.cfm,**.cs,**.gd,**.go,**.htm,**.html,**.js,**.json,**.linq,**.md,**.ps1,**.ts,**.txt,**.xml,**go.mod
REPO_INDEXER_EXCLUDE =
```

### Useful commands
```bash
# View Gitea disk usage.
sudo du -sh /var/lib/gitea
# Show by child directory size.
sudo du -h /var/lib/gitea --max-depth=1
# Show largest directories first.
sudo du -h /var/lib/gitea --max-depth=1 | sort -hr
# Sort by directory name.
sudo du -h /var/lib/gitea --max-depth=1 | sort -k2
# Largest directories.
sudo du --separate-dirs -h /var/lib/gitea | sort -hr | head
sudo du --separate-dirs -h /var/lib/gitea | sort -hr | head -n 2
```
