You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1039 lines
30 KiB

8 months ago
---
title: Problems and solutions with Gitea 1.15
tags: [tutorial, gitea, mariadb, postgresql]
updated: 2021-12-13 11:32:45
8 months ago
description: This blog is now self-hosted
---
My Gitea instance at [software.franco.net.eu.org](https://software.franco.net.eu.org)
has been on SQLite since its inception in October 2018, up until some weeks ago.
I never had any problems concerning database updates. Then I decided to migrate
to something more scalable: [MariaDB](https://mariadb.org/).
<!--TOC-->
- [Migration of Gitea < 1.15.x from SQLite to MariaDB](#migration-of-gitea--115x-from-sqlite-to-mariadb)
- [Update to 1.15.2](#update-to-1152)
- [Revert](#revert)
- [PostgreSQL](#postgresql)
- [Steps](#steps)
8 months ago
- [1. setup the database](#1-setup-the-database)
- [2. recover the repositories](#2-recover-the-repositories)
- [3. Adminer](#3-adminer)
- [Apache configuration](#apache-configuration)
- [4. set the packages on hold](#4-set-the-packages-on-hold)
- [5. restore issues and comments](#5-restore-issues-and-comments)
- [6. restore mirrors from bare repositories](#6-restore-mirrors-from-bare-repositories)
- [7. restore users](#7-restore-users)
- [8. Database backups](#8-database-backups)
8 months ago
- [Extras](#extras)
- [Torification](#torification)
- [HTTP2](#http2)
- [Caching](#caching)
- [Solution](#solution)
- [Redis](#redis)
- [Gitea configuration](#gitea-configuration)
- [Updating gitea next time](#updating-gitea-next-time)
- [Apache2 reverse proxy for Gitea](#apache2-reverse-proxy-for-gitea)
- [Multiple Gitea instances on the same host](#multiple-gitea-instances-on-the-same-host)
- [Gitea configuration](#gitea-configuration-1)
- [Databases](#databases)
- [Systemd service file](#systemd-service-file)
- [Apache virtual host extract](#apache-virtual-host-extract)
- [Listening ports for SSH](#listening-ports-for-ssh)
- [Redis databases](#redis-databases)
7 months ago
- [Updates](#updates)
5 months ago
- [1.15.6 -> 1.15.7](#1156---1157)
- [1.15.2 -> 1.15.6](#1152---1156)
7 months ago
- [GitHub issues](#github-issues)
8 months ago
<!--TOC-->
## Migration of Gitea < 1.15.x from SQLite to MariaDB
Migration was made possible using the provided dump tool.
Here is what I did (these instructions have been written
after some trials and errors):
1. create a MySQL user
```shell
mysql -u root
```
```sql
CREATE USER 'gitea' IDENTIFIED BY '${DB_PASSWORD}';
```
2. create a MySQL database
```sql
CREATE DATABASE giteadb CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
GRANT ALL PRIVILEGES ON giteadb.* TO 'gitea';
FLUSH PRIVILEGES;
exit
```
3. Go into the site administration and delete all authentication sources.
[This issue](https://github.com/go-gitea/gitea/issues/16831)
also happened to me.
4. Stop Gitea
```shell
systemctl stop gitea
```
5. disable all cron jobs at gitea boot. Gitea didn't start while cron jobs
were enabled at boot. Edit `/etc/gitea/app.ini`:
```ini
[cron]
; Enable running cron tasks periodically.
ENABLED = true
; Run cron tasks when Gitea starts.
RUN_AT_START = false
```
6. start and stop Gitea to have a clean restart without cron jobs running:
```shell
systemctl start gitea
sleep 60
systemctl stop gitea
```
7. create a database dump translated from sqlite to mysql. This command creates
a zip file called `gitea-dump-${id}.zip`:
```shell
sudo -i -u gitea
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea dump --skip-repository --skip-log --skip-custom-dir --skip-lfs-data --skip-attachment-data --database mysql -c /etc/gitea/app.ini
```
8. change the database type in `/etc/gitea/app.ini`. Comment out the old section and
add a new mysql section like this:
```ini
[database]
; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice
DB_TYPE = mysql
HOST = 127.0.0.1:3306
NAME = giteadb
USER = gitea
; Use PASSWD = `your password` for quoting if you use special characters in the password.
PASSWD = `${DB_PASSWORD}`
```
9. restore the database:
```shell
unzip gitea-dump-${id}.zip
mysql --default-character-set=utf8mb4 -ugitea -p${DB_PASSWORD} giteadb <gitea-db.sql
```
10. `systemctl start gitea`
11. re-add the authentication sources
This worked although some warnings remained when I lauched Gitea's doctor command.
## Update to 1.15.2
After updating the packages, Gitea did not start.
There were a bunch of errors (for example
[this](https://github.com/go-gitea/gitea/issues/16961))! I was able to recover the database
by hand by having a look at the errors from the log.
After some time, however, I noticed that the mirror feature did not work
and the repositories on the web UI did not update after pushing from git.
[Jump to the solution](#solution)
### Revert
I tried reverting back to a previous database version but once you migrate
you cannot go back easily.
### PostgreSQL
I tried with a fresh PostgreSQL 13 database and Gitea 1.15.2.
The repostitory and mirror problem was still there so at least I knew it
wasn't a problem with the database.
What I did in the end was to re-install Gitea 1.14.7 and to switch to
another new PostgreSQL database instead. The problem now was that
I needed to recover most "issues", mirrors, users, etc... from the original
MariaDB database.
Once that was done after hard work I made a backup and proceeded
to the migration of this new database to Gitea 1.15.0.
#### Steps
These steps work on Debian GNU/Linux 10 which is now *oldstable*.
8 months ago
##### 1. setup the database
8 months ago
1. install PostgreSQL 13 from the [official website](https://www.postgresql.org/download/linux/debian/)
2. Follow the [database preparations instructions](https://docs.gitea.io/en-us/database-prep/#postgresql)
3. use the UNIX socket instead of TCP. This configuration might improve performance a little bit. Set this in `/etc/gitea/app.ini`
```ini
[database]
DB_TYPE = postgres
HOST = /var/run/postgresql
LOG_SQL = false
```
8 months ago
##### 2. recover the repositories
8 months ago
Create the users and push or "adopt" the repositories through the `admin/repos` URL. You will see
the `Unadopted Repository` button there.
8 months ago
##### 3. Adminer
8 months ago
[Adminer](https://www.adminer.org/) is similar to phpMyAdmin. You can install it with:
```shell
apt-get install adminer/buster-backports
```
The backports version seem to be fully compatible with PostgreSQL 13.
8 months ago
###### Apache configuration
8 months ago
1. if you use [PHP-FPM](https://www.php.net/manual/en/install.fpm.php)
you can use this snippet in a `VirtualHost` directive:
```apache
Alias /dbadmin /usr/share/adminer/adminer/
<Directory "/usr/share/adminer/adminer/">
Require ip 127.0.0.1
Require ip 192.168.0.
Options FollowSymlinks
</Directory>
Include conf-enabled/php7.3-fpm.conf
```
2. add this to the php.ini file of Apache, in `/etc/php/7.3/apache2/php.ini`:
```ini
[HOST=my.host]
open_basedir = /tmp/:/usr/share/adminer:/usr/share/php:/var/log/adminer
```
3. finally:
```shell
systemctl restart apache2
```
4. connect to `http://my.host/dbadmin`
8 months ago
##### 4. set the packages on hold
8 months ago
Set these packages on hold so when you update the system they don't get
updated by accident.
```shell
apt-mark hold gitea linux-image-amd64 postgresql-13 postgresql-client-13 postgresql-client-common postgresql-common
```
This is what you should get when you run `apt-mark showhold`:
```shell
gitea
linux-image-amd64
postgresql-13
postgresql-client-13
postgresql-client-common
postgresql-common
```
8 months ago
##### 5. restore issues and comments
8 months ago
1. open the original database with adminer
1. get the repository id. Use the `repository` table to get it. Let's say it's `38`
2. go to the `issue` table
3. click on the search filter on the top. Set `repo_id` `=` `38`. Then click `Select`
4. on the web-ui with the new database create new issues within the repository. In our example we have 9
issues so we need to create 9 dummy issues. Comment content and the user creating them is irrelevant
5. now take note of the issues ids. In our case they are [`1`-`9`]
6. open the comment table and do a new query, filtering by issue id. Let's start with `1`
In this case we only have 1 comment so we must create a dummy comment in the issue on web UI
7. for issue `2` we have 2 comments so we need to create 2 dummy comments
8. do this for issues [`1`-`9`]
9. once we have all the dummy data we can open the new database on adminer.
What we have to do now is just to manually copy-paste all the data from
one database to the other. Check the UI once in a while if everything is working
{% include image.html file="adminer_gitea_issue_table.png" alt="Gitea issue table on Adminer" caption="Gitea issue table on Adminer" %}
{% include image.html file="adminer_gitea_comment_table.png" alt="Gitea comment table on Adminer" caption="Gitea comment table on Adminer" %}
{% include image.html file="adminer_gitea_comment_table_2.png" alt="Gitea comment table for issue 2 on Adminer" caption="Gitea comment table for issue 2 on Adminer" %}
8 months ago
##### 6. restore mirrors from bare repositories
8 months ago
1. once you have the repositories go into the `repositories` table
2. select the to-be mirrors repositories and set the `is_mirror` variable to `true`
2. go into the `mirror` table and create a new element. Use the correct `repo_id`.
{% include image.html file="adminer_gitea_repository_table_mirror.png" alt="Mirror variable in a repository" caption="Mirror variable in a repository" %}
{% include image.html file="adminer_gitea_mirror_table.png" alt="An example row of the mirror table" caption="An example row of the mirror table" %}
8 months ago
##### 7. restore users
8 months ago
To restore users simply create new users using Gitea's admin interface and then copy-paste the data
in the rows.
8 months ago
##### 8. Database backups
8 months ago
I now use 15 minute separated backups using borgmatic. See also
[https://docs.franco.net.eu.org/automated-tasks/scripts.html#borgmatic-hooks-py](https://docs.franco.net.eu.org/automated-tasks/scripts.html#borgmatic-hooks-py)
This is just an example for reference:
```yaml
#
# borgmatic.iron_postgresql_giteadb.yaml
#
# Copyright (C) 2014-2020 Dan Helfman <https://torsion.org/borgmatic/docs/reference/config.yaml>
# 2021 Franco Masotti
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
location:
source_directories: []
repositories:
- user@remotepc:backups/postgresql_giteadb.borg
storage:
checkpoint_interval: 900
lock_wait: 120
retention:
keep_within: 1w
keep_monthly: 1
consistency:
checks:
- archives
output:
color: false
hooks:
after_everything:
- /home/jobs/scripts/by-user/root/borgmatic_hooks.py /home/jobs/scripts/by-user/root/borgmatic_hooks.iron_postgresql_giteadb.yaml 'finish' "{configuration_filename}" "{repository}" "{output}" "{error}"
on_error:
- /home/jobs/scripts/by-user/root/borgmatic_hooks.py /home/jobs/scripts/by-user/root/borgmatic_hooks.iron_postgresql_giteadb.yaml 'error' "{configuration_filename}" "{repository}" "{output}" "{error}"
postgresql_databases:
- name: giteadb
# Use unix sockets instead of TCP.
# See
# https://torsion.org/borgmatic/docs/reference/configuration/
#
# hostname: 127.0.0.1
# port: 5432
username: gitea
password: ${DB_PASS}
format: tar
options: "--verbose"
```
## Extras
### Torification
This is useful if you need to clone repositories, or do mirroring via TOR.
I did this before switching to PostgreSQL:
1. Install TOR and configure it
```shell
apt-get install tor
```
2. run `systemctl edit gitea.service` and add this content:
```systemd
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=mysqld.service
After=postgresql.service
After=memcached.service
After=redis.service
# Comment or change these.
Requires=network.target
Requires=postgresql.service
Requires=redis.service
# Comment this if you don't need it.
# See
# https://docs.franco.net.eu.org/automated-tasks/scripts.html#notify-unit-status-py
OnFailure=notify-unit-status@%n.service
[Service]
ExecStart=
ExecStart=/usr/bin/torsocks --isolate /usr/bin/gitea web -c /etc/gitea/app.ini
User=gitea
Group=gitea
Type=simple
WorkingDirectory=~
RuntimeDirectory=gitea
LogsDirectory=gitea
StateDirectory=gitea
Environment=USER=gitea HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea
Restart=always
RestartSec=2s
CapabilityBoundingSet=
NoNewPrivileges=false
#SecureBits=noroot-locked
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/etc/gitea/app.ini
PrivateTmp=true
PrivateDevices=false
PrivateUsers=false
ProtectHostname=false
ProtectClock=false
ProtectKernelTunables=false
ProtectKernelModules=false
ProtectKernelLogs=false
ProtectControlGroups=true
LockPersonality=false
MemoryDenyWriteExecute=false
RestrictRealtime=false
RestrictSUIDSGID=false
SystemCallArchitectures=
SystemCallFilter=
SystemCallErrorNumber=EPERM
ReadWriteDirectories=/var/spool/postfix/maildrop
```
3. restart gitea
```shell
systemctl restart gitea.servvice
```
4. Test by cloning a repository from *The Tor Project*. Mirror this
repository for example:
[http://eweiibe6tdjsdprb4px6rqrzzcsi22m4koia44kc5pcjr7nec2rlxyad.onion/tpo/anti-censorship/bridgedb.git](http://eweiibe6tdjsdprb4px6rqrzzcsi22m4koia44kc5pcjr7nec2rlxyad.onion/tpo/anti-censorship/bridgedb.git)
### HTTP2
1. enable HTTP2 on Apache
```shell
a2enmod http2
```
2. add this to your Apache configuration file. This setting can be global or
per-virtualhost:
```apache
Protocols h2 h2c http/1.1
```
3. if you have problems with HTTP2 add this to `/etc/gitea/app.ini`:
```ini
[ui.notification]
EVENT_SOURCE_UPDATE_TIME=-1
```
See also [https://github.com/go-gitea/gitea/issues/11978](https://github.com/go-gitea/gitea/issues/11978)
### Caching
#### Solution
The repository/mirror problem was still there. After lots of trials and errors I found
a solution.
##### Redis
1. install Redis
```shell
apt-get install redis-server
```
2. setup Redis to listen on a UNIX socket exclusively. Edit `/etc/redis/redis.conf`:
```conf
unixsocket /var/run/redis/redis-server.sock
unixsocketperm 770
bind 127.0.0.1 ::1
# This disables listening on TCP.
port 0
# Avoid saving on disk
save ""
# Remove authentication.
requirepass ""
```
3. add the `gitea` user to the `redis` group so Gitea can have
access to the socket.
```
usermod -aG redis gitea
```
4. restart Redis and Gitea:
```shell
systemctl restart redis-server.service gitea.service
```
5. check the logs at `/var/log/redis/redis-server.log`. If you have a warning
about transparent hugepages. Add this service to Systemd.
```systemd
# See
# https://unix.stackexchange.com/a/363887
# https://stackoverflow.com/a/64945381
# CC BY-SA 3.0
# (c) 2017 nelaaro
[Unit]
Description=madvise Transparent Huge Pages
Before=redis-server.service
Before=apache2.service
Before=gitea.service
Before=postgresql.service
[Service]
Type=oneshot
ExecStart=/bin/sh -c "/usr/bin/echo "madvise" | tee /sys/kernel/mm/transparent_hugepage/enabled"
ExecStart=/bin/sh -c "/usr/bin/echo "madvise" | tee /sys/kernel/mm/transparent_hugepage/defrag"
[Install]
WantedBy=multi-user.target
```
6. have a look at the [Redis ArchWiki page](https://wiki.archlinux.org/title/Redis).
##### Gitea configuration
To be able to use Redis in Gitea edit these sections in `/etc/gitea/app.ini`:
```ini
[cache]
ADAPTER = redis
HOST = network=unix,addr=/var/run/redis/redis-server.sock,db=0,pool_size=100,idle_timeout=180s
ITEM_TTL = 24h
[session]
PROVIDER = redis
PROVIDER_CONFIG = network=unix,addr=/var/run/redis/redis-server.sock,db=1,pool_size=100,idle_timeout=180s
[queue]
TYPE = redis
CONN_STR = network=unix,addr=/var/run/redis/redis-server.sock,db=2,pool_size=100,idle_timeout=180s
[queue.task]
QUEUE_TYPE = redis
QUEUE_CONN_STR = network=unix,addr=/var/run/redis/redis-server.sock,db=2,pool_size=100,idle_timeout=180s
[task]
QUEUE_TYPE = redis
QUEUE_CONN_STR = network=unix,addr=/var/run/redis/redis-server.sock,db=2,pool_size=100,idle_timeout=180s
```
**Note: using Redis for queues and tasks seems to have solved the original problem.**
### Updating gitea next time
5 months ago
1. wait at least one week before updating. Check
[issues](https://github.com/go-gitea/gitea/issues)
for the new version
8 months ago
5 months ago
2. temporarly disable the service
```shell
8 months ago
systemctl stop gitea.service
systemctl mask gitea.service
```
5 months ago
3. copy the original database into a new one
8 months ago
8 months ago
```shell
sudo -i -u postgres
psql
```
8 months ago
```sql
7 months ago
CREATE DATABASE backup_giteadb_${major}_${minor}_${patch} WITH TEMPLATE giteadb;
8 months ago
```
7 months ago
where `major`, `minor` and `patch` correspond to the current Gitea version.
5 months ago
4. run the doctor on the original database
8 months ago
```shell
8 months ago
exit
7 months ago
exit
8 months ago
sudo -i -u gitea
8 months ago
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini doctor --all
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini doctor --all --fix
```
5 months ago
5. update Gitea
8 months ago
```shell
8 months ago
exit
sudo -i
8 months ago
apt-mark unhold gitea
apt-get update
apt-get dist-upgrade
```
5 months ago
6. migrate the database
8 months ago
```bash
8 months ago
exit
sudo -i -u gitea
8 months ago
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini migrate
```
5 months ago
7. run the doctor again
8 months ago
```shell
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini doctor --all
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini doctor --all --fix
```
5 months ago
8. re-enable the service
8 months ago
```shell
8 months ago
exit
sudo -i
8 months ago
systemctl unmask gitea.service
systemctl start gitea.service
8 months ago
apt-mark hold gitea
8 months ago
```
5 months ago
9. if everything works remove the previous database dump if applicable:
```shell
sudo -i -u psql
psql
```
```SQL
DROP DATABASE backup_giteadb_${old_major}_${old_minor}_${old_patch}
```
8 months ago
### Apache2 reverse proxy for Gitea
1. modify Gitea configuration (`/etc/gitea/app.ini`):
```ini
[server]
PROTOCOL = unix
DOMAIN = localhost
HTTP_ADDR = /var/run/gitea/gitea.sock
UNIX_SOCKET_PERMISSION = 770
; Do not set this variable if PROTOCOL is set to 'unix'.
# LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
```
2. Add the www-data user to gitea's group so it can access the socket.
```shell
usermod -aG gitea www-data
```
3. Restart gitea and apache
```shell
systemctl restart gitea.service apache2.service
```
4. clearnet configuration in `/etc/apache2/apache2.conf` or a virtual host file:
8 months ago
variables (shell style):
- `ONION_ADDRESS`: the TOR address where Gitea is exposed
- `TCP_PORT`: the TCP/IP port where gitea should be listenting.
Even if we are using a UNIX socket this is applicable. You can use Gitea's default port.
- `SERVER_NAME`: the FQDN
```apache
#########
# Gitea #
#########
<IfModule mod_ssl.c>
<VirtualHost *:443>
UseCanonicalName on
ProxyPreserveHost On
Keepalive On
RewriteEngine on
AllowEncodedSlashes NoDecode
ServerName ${SERVER_NAME}
ProxyBadHeader Ignore
# TOR.
# Remove this if you don't want Gitea being avaliable on TOR.
ServerAlias ${ONION_ADDRESS}
Header set Onion-Location "http://${ONION_ADDRESS}%{REQUEST_URI}s"
SSLCompression off
ProxyPass / unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/ nocanon
ProxyPassReverse / unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/${SERVER_NAME}/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/${SERVER_NAME}/privkey.pem
</VirtualHost>
```
5. if you use TOR add this configuration in `/etc/apache2/apache2.conf` or a virtual host file:
8 months ago
variables (shell style):
- `TCP_PORT`: the TCP/IP port where Gitea should be listenting. Even if we are using a UNIX socket this is applicable. You can use Gitea's default port
- `APACHE_TCP_PORT`: the TCP/IP port where Apache is listening
- `SERVER_NAME`: TOR's FQDN
```apache
#########
# Gitea #
#########
<IfModule mod_ssl.c>
<VirtualHost *:${APACHE_TCP_PORT}>
7 months ago
UseCanonicalName on
ProxyPreserveHost On
ProxyRequests off
AllowEncodedSlashes NoDecode
Keepalive On
RewriteEngine on
ServerName ${SERVER_NAME}
SSLCompression off
# Disable HTTP push and cloning for TOR.
# TODO: enable only cloning but not push.
RewriteRule ^(.*)/info/refs /errors
<Location "/errors">
Deny from all
</Location>
# Redirect api and login to black holes.
# Specific rules first, generic rules last.
ProxyPass /user/login unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/404 nocanon
ProxyPassReverse /user/login/ unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/404
ProxyPass /api unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/404 nocanon
ProxyPassReverse /api unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/404
ProxyPass / unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/ nocanon
ProxyPassReverse / unix:/var/run/gitea/gitea.sock|http://127.0.0.1:${TCP_PORT}/
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Port "${APACHE_TCP_PORT}"
RequestHeader set X-Forwarded-Host "${SERVER_NAME}"
# Distinguish normal traffic from tor's.
RequestHeader set X-Forwarded-For "tor"
8 months ago
</VirtualHost>
</IfModule>
```
6. if you use TOR, add this to `/etc/tor/torrc`
8 months ago
variables (shell style):
- `APACHE_TCP_PORT`: the TCP/IP port where Apache is listening
```conf
HiddenServiceDir /var/lib/tor/gitea/
HiddenServicePort 80 127.0.0.1:${APACHE_TCP_PORT}
```
Follow [these](https://2019.www.torproject.org/docs/tor-onion-service) instructions.
See these links for the UNIX socket explanation:
- [https://httpd.apache.org/docs/trunk/mod/mod_proxy.html#proxypass](https://httpd.apache.org/docs/trunk/mod/mod_proxy.html#proxypass)
- [https://wiki.archlinux.org/title/Talk:Gitea#Apache_Reverse_Proxy_Over_Unix_Socket](https://wiki.archlinux.org/title/Talk:Gitea#Apache_Reverse_Proxy_Over_Unix_Socket)
## Multiple Gitea instances on the same host
8 months ago
With a few tricks you can manage any number of gitea instances on the same hosts.
I'm running two at the moment.
5 months ago
Using all the above configurations you will need the following:
7 months ago
- 2 databases
- 2 Gitea sockets. This step is very important
otherwise nothing works
- 2 listening ports for SSH-based operations
- 2 app.ini configuration files
- 2 (* n) Redis databases
- 2 Gitea Systemd service unit files
7 months ago
In this example we have two instances running at:
- `my.domain.org`, SSH port 2112
- `my.other.domain.org`, SSH port 2222
Domains are called `FQDN` in variables from now on.
### Gitea configuration
1. copy the configuration file.
```shell
cp -aR /etc/gitea/app.ini /etc/gitea/${FQDN}.app.ini
```
2. edit these values as explained later:
| app.ini variable name | Description | Value | Scope |
|-----------------------|-------------|-------|-------|
| `APP_NAME` | - | `${FQDN}` | - |
| `repository.ROOT` | - | `/var/lib/gitea/${FQDN}/repos` | - |
| `server.ROOT_URL` | - | `https://${FQDN}/` | Apache |
| `server.HTTP_ADDR` | the UNIX socket path of the new Gitea instance | `/var/run/${FQDN}.gitea/gitea.sock` | Apache, Systemd (as `RuntimeDirectory`) |
| `server.SSH_DOMAIN` | same as the domain in the HTTP URL | `${FQDN}` | OpenSSH |
| `server.SSH_PORT` | see the SSH port section below | 2112 and 2222 in this example | OpenSSH |
| `server.SSH_ROOT_PATH` | - | `/var/lib/gitea/${FQDN}/.ssh` | OpenSSH |
| `server.APP_DATA_PATH` | - | `/var/lib/gitea/${FQDN}/data` | - |
| `log.file.FILE_NAME` | - | `/var/log/gitea/${FQDN}.log` | Fail2ban (if you use it) |
| `database.NAME` | the name of the new Gitea database | `echo giteadb_"$(echo -n "${FQDN}" | tr '.' '_')"` | PostgreSQL |
| `cache.HOST` | change the redis `db` value | - | Redis |
| `session.PROVIDER_CONFIG` | change the redis `db` value | - | Redis |
| `queue.CONN_STR` | change the redis `db` value | - | Redis |
| `queue.task.QUEUE_CONN_STR` | change the redis `db` value | - | Redis |
| `task.QUEUE_CONN_STR` | change the redis `db` value | - | Redis |
### Databases
1. create a second database as usual
(see the [instructions on Gitea docs](https://docs.gitea.io/en-us/database-prep/#postgresql)).
2. add the Borgmatic backup service for the new database
### Systemd service file
7 months ago
```ini
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=mysqld.service
After=postgresql.service
After=memcached.service
After=redis.service
# Comment or change these.
Requires=network.target
Requires=postgresql.service
Requires=redis.service
OnFailure=notify-unit-status@%n.service
[Service]
ExecStart=
ExecStart=/usr/bin/gitea web -c /etc/gitea/${FQDN}.app.ini
User=gitea
Group=gitea
Type=simple
WorkingDirectory=~
RuntimeDirectory=${FQDN}.gitea
LogsDirectory=gitea
StateDirectory=gitea
Environment=USER=gitea HOME=/var/lib/gitea/${FQDN} GITEA_WORK_DIR=/var/lib/gitea/${FQDN}
Restart=always
RestartSec=2s
CapabilityBoundingSet=
NoNewPrivileges=false
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/etc/gitea/${FQDN}.app.ini
PrivateTmp=true
PrivateDevices=false
PrivateUsers=false
ProtectHostname=false
ProtectClock=false
ProtectKernelTunables=false
ProtectKernelModules=false
ProtectKernelLogs=false
ProtectControlGroups=true
LockPersonality=false
MemoryDenyWriteExecute=false
RestrictRealtime=false
RestrictSUIDSGID=false
SystemCallArchitectures=
SystemCallFilter=
SystemCallErrorNumber=EPERM
ReadWriteDirectories=/var/spool/postfix/maildrop
7 months ago
```
### Apache virtual host extract
Remember to change the port number. Here is set to `3000` as an example.
```apache
<IfModule mod_ssl.c>
<VirtualHost *:443>
UseCanonicalName on
ProxyPreserveHost On
Keepalive On
RewriteEngine on
AllowEncodedSlashes NoDecode
ServerName ${FQDN}
ProxyBadHeader Ignore
SSLCompression off
ProxyPass / unix:/var/run/${FQDN}.gitea/gitea.sock|http://127.0.0.1:3000/ nocanon
ProxyPassReverse / unix:/var/run/${FQDN}.gitea/gitea.sock|http://127.0.0.1:3000/
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/${FQDN}/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/${FQDN}/privkey.pem
</VirtualHost>
</IfModule>
7 months ago
```
### Listening ports for SSH
1. separate the two authorized keys files based on port.
What follows is an example extract of `/etc/ssh/sshd_config` that enables
this setup. `user1`, `user2` and `user3` are example users
you might have in your sshd configuration file
```conf
Port 22
Port 33
# my.domain.org
Port 2112
# my.other.domain.org
Port 2222
#########
# Users #
#########
# Exclude all other from 30000 and 30001.
Match LocalPort 2112
DenyUsers user1 user2 user3
AllowUsers gitea
Match LocalPort 2222
DenyUsers user1 user2 user3
AllowUsers gitea
# Exclude gitea.
Match LocalPort 22
DenyUsers gitea
AllowUsers user1 user2 user3
# An extra SSH port.
Match LocalPort 33
DenyUsers gitea
AllowUsers user1 user2 user3
#######################
# Gitea my.domain.org #
#######################
Match User gitea LocalPort 2112
IPQoS throughput
X11Forwarding no
PermitTTY no
AllowTcpForwarding no
AuthorizedKeysFile .ssh/authorized_keys my.domain.org/.ssh/authorized_keys
#############################
# Gitea my.other.domain.org #
#############################
Match User gitea LocalPort 2222
IPQoS throughput
X11Forwarding no
PermitTTY no
AllowTcpForwarding no
AuthorizedKeysFile my.other.domain.org/.ssh/authorized_keys
```
2. remember to open the new SSH ports in iptables if needed
### Redis databases
1. increase the number of databases in `/etc/redis/redis.conf`:
```conf
databases 32
```
2. restart Redis
```shell
systemctl restart redis
```
## Updates
5 months ago
### 1.15.6 -> 1.15.7
Still the same error:
```
[4] Check consistency of database
- [C] Error: pq: syntax error at or near "." whilst counting Collaborations without existing user
```
This happens after the migration:
```shell
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini migrate
```
```
2021/12/10 18:16:38 ...om/urfave/cli/app.go:277:Run() [W] Table user Column max_repo_creation db default is '-1', struct default is -1
2021/12/10 18:16:38 ...om/urfave/cli/app.go:277:Run() [W] Table email_address Column lower_email db nullable is true, struct nullable is false
2021/12/10 18:16:38 ...om/urfave/cli/app.go:277:Run() [W] Table external_login_user column avatar_url db type is TEXT, struct type is VARCHAR(255)
```
### 1.15.2 -> 1.15.6
After updating from 1.15.2 to 1.15.6, when running:
```shell
HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea /usr/bin/gitea -c /etc/gitea/app.ini doctor --all --fix
```
I get this:
```
[4] Check consistency of database
- [C] Error: pq: syntax error at or near "." whilst counting Collaborations without existing user
```
7 months ago
### GitHub issues
- [16992](https://github.com/go-gitea/gitea/issues/16992)
- [17485](https://github.com/go-gitea/gitea/issues/17485)