Migrating Friendica to Docker

1/20/2021

After my friends and I migrated from DigitalOcean to Vultr, I still had to set my Friendica instance back up. Here I talk about that process.

What is Friendica?

Friendica is self-hostable social media software. Unlike traditional social media like Facebook or Twitter, individuals can run their own copy of Friendica, and interact with users on other servers running Friendica or similar software (Mastodon is another popular one).

Friendica Project Website

Situation

I've been running my instance at social.thorjhanson.com for about 2 years now. Initially, I installed it directly to our DigitalOcean server running Apache. With our new server at Vultr, we had decided we wanted to run as much of the software as we could in containers (in this case, Docker). In the month or so leading up to the migration, I had tried several times to convert my existing installation to a Docker container, without success. I ended up making a dump of the database, zipping up the data directory, and backing them up to be re-investigated after our Vultr migration.

Friendica consists of a PHP-driven front end (which has some directories with data in them) and a MariaDB database for holding the bulk of the instance information. There is also a cron job that is required to fire every few minutes to complete scheduled tasks on the server. Its construction strongly resembles Nextcloud, which is why I felt pretty confident following the same formula they recommended for transferring from a native to a Docker installation. Here's what ended up working for me.

Note: I am not responsible for any outcomes that may result from following advice on this page, including but not limited to LOSS OF DATA. Always make sure your system is backed up before attempting something like this.

Migration

Overview:

  • Set up a docker-compose file to define the 3 containers: database, instance, and cron job
  • Dump the existing database to a file
  • Start the database container
  • Import the data into the database
  • Unzip the archive of the data files from the original installation
  • Edit the configuration file to point to the new database, etc.
  • Start up the instance container and the cron job container
  • Ensure the reverse proxy is configured to point to the docker container

Exporting the Data

First, the mariadb-dump command should be used to to "export" the database to a file. The command takes similar parameters as the regular mariadb client, but will dump the entire database to a file so it can be re-imported later. This process may take several minutes, or even longer depending upon the size of the database. If the database is named friendica, the command might look something like this:

mariadb-dump --user=root --password=rootsqlpassword friendica > ./backup-file-friendica.sql

Once that was done, it is good to make an archive of the entire installation directory (if the host to docker conversion is being performed on one machine, this step could probably be skipped and the files cpd directly later). For example, if Friendica was originally installed to /var/www/friendica, a command like the following would roll the entire directory up into a .tar.gz:

tar --acls --xattrs -cpvf "./friendicabackup.tar.gz" "/var/www/friendica"

These two files (the sql and the tar.gz) can be used as a backup of the whole instance, or (in my case) can be used to migrate the installation to a new machine.

Importing the Data

Once on the destination machine, a carefully-crafted docker-compose.yml is needed. I'll link an annotated example of mine, but each configuration will require its own adjustments. The friendica-docker GitHub repository has more information. For a person who has no experience with docker or docker-compose, additional background research will be required.

example docker-compose.yml

Friendica container on GitHub

With a docker-compose file, the database container can be brought up by itself:

docker-compose up -d db

Once the container is up, the backup file can be copied in, imported into the database, and the backup file can be removed from the container:

docker cp ./backup-file-friendica.sql friendica-db:/db.sql
docker exec db sh -c "mariadb --user=root --password=password friendica < /db.sql"
docker exec db sh -c "rm /db.sql"

In my case, I did this operation as the friendica user rather than root. This, however, required me to add SUPER permissions to the friendica user in order for the database to import. Logging in as the root user in the database should avoid this problem.

Once the database import is done, the friendicabackup.tar.gz needs to be extracted to whatever location was selected in the docker-compose.yml as the persistent storage location. In the example docker-compose, the commands would look something like this:

cd /persistent/friendica
tar -xvf ~/friendicabackup.tar.gz

Reconfigure

At this point, the Friendica configuration file itself needs to be adjusted to point to the new database:

nano /persistent/friendica/friendica/config/local.config.php

In particular, the database hostname should be the name of the container on the docker network - in my example, that was friendica-db.

With all the files in place and edited, the entire works can be brought up:

docker-compose up -d

Reverse Proxy

The final step is to set up the reverse proxy. This ended up being my original source of failure. Most references available assume ngnix is being used for proxying, but I'm using Apache. It turns out ProxyPreserveHost On is critical for Friendica to function behind a reverse proxy. Here's a sample of what an Apache reverse proxy file might look like:

<VirtualHost *:443>

ServerName social.example.com
SSLEngine on

SSLCertificateFile /path/to/fullchain.pem
SSLCertificateKeyFile /path/to/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

ErrorLog ${APACHE_LOG_DIR}/friendica-error.log
CustomLog ${APACHE_LOG_DIR}/friendica-access.log combined

ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"

ProxyPass / http://localhost:1090/
ProxyPassReverse / http://localhost:1090/

</VirtualHost>

There is a lot of variation in what each particular setup will need, but this should be a good base idea as to what Friendica is expecting.

The Docker image of Friendica itself is fairly new, and so there is still some trial-and-error/pain points in the setup. Some of the items in their GitHub issue tracker might be useful to someone experiencing problems:

Issue Tracker

Complete!

With Apache configured and reloaded, Friendica should now be fully operational. The admin panel will often have any warnings if there are configuration mistakes. The section labelled "DB updates" should be looked at, since it can often automatically correct database issues, as well as the "Inspect Worker Queue", since it can indicate if the cron container is failing to process the jobs.

Additionally, the docker logs command is helpful to see if any of the containers are experiencing issues.

Conclusion

It took me several tries to migrate Friendica, but I became a lot more familiar with the process of importing databases along the way. My overall comfort level working with docker, docker-compose, and Mariadb has improved as well. While I wish I would have thought to try the ProxyPreserveHost option sooner, it is definitely one of the first solutions I will consider when putting applications behind a reverse proxy.

Oh, and y'know how I mentioned Nextcloud and Friendica have a lot in common? I found out Nextcloud needs the ProxyPreserveHost option, too - about a month ago. I should have guessed it'd be important here.

Back to Blog