
Hello everyone!

This is my first blog post in 2025, and Iād like to talk about my experience inself-hosting PeerTube in Fedora Server andhow to do it yourself.
In addition to this Iāve also added a new category on my blog: Self Hosting
I also want to celebrate I have 15k unique visitors per month (according to CloudFlare), however most of themare port scans, exploits and LLM-bots scraping everything and ignoring robots.txt.

Why PeerTube
PeerTube is a federated video sharing platform. You can host your own instance or create an account on a popularinstance like:The federation allows every instance to have its own rules and also allow users from different instancesto interact with each other.
Federation also helps prevent monopoly and censorship.
My YouTube channel is small and my goal is not to become an influencer. I just like making videos from time to timeand own my data.
Fedora Server
Iāve asked the Fediverse what should I use to host virtual machines, and they answered Fedora Server! I was so impressedthat Iāve also decided to host other stuff here as well.Denis NuČiu (@nuculabs@mastodon.social)
I'm running Ubuntu server on my old PC at home and I'd like to install and manage virtual machines on it and control them via web VNC (noVNC). Is there any open source or paid software that allows me to do that? #askfedi #selfhost

Before Fedora Server I had PeerTube on a Raspberry Pi5 with 4GB of RAM and then a PC running Ubuntu Server. Iāveuninstalled Ubuntu Server and installed Fedora Server.
The PI5 didnāt work that well in encoding videos department. A simple 5 minutes videos could take up to 20minutesto be encoded in 1080p, 720p and 480p resolutions. There was also a limited number of simultaneous playbacks supported.
Iām sticking with Fedora Server thanks to the Cockpit UI, Podman support and virtualmachine support. Having virtual machines run on a separated PC and connecting to them in the browser is a huge benefitfor my use cases.

Prerequisites
To keep this article short, if you want to host PeerTube on a Fedora Server with Podman youāll need these prerequisites:- Self Host PeerTube on your PC via Docker
- Have Fedora Server, Podman and a working SSH connection to the server.
How to Self Host PeerTube on Fedora Server with Podman
You can use my docker-compose.yaml file with podman compose or use your own.For my case Iām hosting PostgresSQL on a separate server, and Iām mounting the Podman volumes over the network via samba.Iām also using a reverse proxy configured on another system, so Iāve removed the containers from theofficial docker-compose.yaml file.
YAML:
services:
peertube:
container_name: peertube_peertube_1
image: chocobozzz/peertube:v7.0.0-bookworm
# Use a static IP for this container because nginx does not handle proxy host change without reload
# This container could be restarted on crash or until the postgresql database is ready for connection
networks:
default:
ipv4_address: 173.18.0.42
ipv6_address: fdab:e4b3:21a2:ef1b::42
env_file:
- .env
ports:
- "1935:1935" # Comment if you don't want to use the live feature
- "9000:9000"
volumes:
- /mnt/peertube/data:/data # /mnt/peertube is a samba volume
- /mnt/peertube/config:/config
depends_on:
- redis
restart: "always"
security_opt:
- "label=type:peertube_peertube_1.process"
# - "seccomp=unconfined"
redis:
image: redis:6-alpine
restart: "always"
networks:
default:
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 173.18.0.0/16
- subnet: fdab:e4b3:21a2:ef1b::/64
(Optional) Setting up Samba volumes
To set up the samba volumes Iāve created a peertube user withsudo useradd peertube
Then Iāve modified /etc/fstab to automatically mount the network volumes:
//<ip-of-storage-server>/peertube/ /mnt/peertube cifs uid=peertube,gid=peertube,file_mode=0777,dir_mode=0777,username=peertube,password=peertube 0 0
To allow Podman to access the cifs volumes I had to run the following command.
This command modifies the SELinux system-wide settings and allows every virtual machinesto access CIFS file (Samba Drive).
sudo semanage boolean -m virt_use_samba --on
Loading SELinux policies
SELinux can be confusing
I still donāt know to use it properly but with some trial and error tinkering I got PeerTube to work.
Youāll need to install:
dnf install udica container-selinux
Once you have udica installed you can save the following content to a file called: peertube_peertube_1.cil
The file contains all the permissions needed by peer tube to function correctly.
Code:
(block peertube_peertube_1
(blockinherit container)
(blockinherit restricted_net_container)
(allow process process ( capability ( chown dac_override fowner fsetid kill net_bind_service setfcap setgid setpcap setuid sys_chroot )))
(allow process flash_port_t ( tcp_socket ( name_bind )))
(allow process http_port_t ( tcp_socket ( name_bind )))
(allow process unreserved_port_t (tcp_socket (name_connect) ) )
(allow process cifs_t (dir (setattr)))
(allow process redis_port_t (tcp_socket (name_connect)))
(allow process smtp_port_t (tcp_socket (name_connect)))
(allow process container_file_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write )))
(allow process container_file_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write )))
(allow process container_file_t ( fifo_file ( getattr read write append ioctl lock open )))
(allow process container_file_t ( sock_file ( append getattr open read write )))
(allow process user_home_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write )))
(allow process user_home_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write )))
(allow process user_home_t ( fifo_file ( getattr read write append ioctl lock open )))
(allow process user_home_t ( sock_file ( append getattr open read write )))
)
After that you will need to load it with the following commands:
Code:
sudo semodule -i peertube_peertube_1.cil /usr/share/udica/templates/{base_container.cil,net_container.cil}
Troubleshooting SELinux
SELinux policies are not that intuitive. I didnāt get PeerTube running with the default policies and I had to edit them.
To generate default policies you will need to have the container created and run:
Code:
podman inspect peertube_peertube_1 > peertube_peertube_1.json
sudo udica -j peertube_peertube_1.json peertube_peertube_1
This will generate the default .cil policies. If you load them and run the containers
Code:
sudo semodule -i peertube_peertube_1.cil /usr/share/udica/templates/{base_container.cil,net_container.cil}
podman compose up
You will encounter various errors, like for example the PeerTube container cannot connect to Redis.
Udica didnāt detect it and SELinux is preventing the TCP connection in order to protect your system from unwanted behaviour.
All these policy violations are logged in the audit.log file at /var/share/audit/audit.log.
You can the use a command audit2allow to generate the remaining policies.
Code:
sudo cat /var/log/audit/audit.log | audit2allow -a -C > audit.txt
On my machine, when I completed the setup the final audit.txt file looked like this:
Code:
;============= container_t ==============
;!!!! This avc is allowed in the current policy
(allow container_t cifs_t (dir (setattr)))
(allow container_t user_home_t (dir (setattr)))
;============= peertube_peertube_1.process ==============
;!!!! This avc is allowed in the current policy
(allow peertube_peertube_1.process cifs_t (dir (setattr)))
;!!!! This avc is allowed in the current policy
(allow peertube_peertube_1.process redis_port_t (tcp_socket (name_connect)))
;!!!! This avc is allowed in the current policy
(allow peertube_peertube_1.process smtp_port_t (tcp_socket (name_connect)))
;!!!! This avc is allowed in the current policy
(allow peertube_peertube_1.process unreserved_port_t (tcp_socket (name_connect)))
;============= systemd_homed_t ==============
(allow systemd_homed_t var_t (dir (read)))
;============= systemd_logind_t ==============
(allow systemd_logind_t iptables_var_run_t (dir (read)))
All that was left to do is copy and modify the denied policies to the peertube_peertube_1.cil file.
For example:
Code:
(allow peertube_peertube_1.process redis_port_t (tcp_socket (name_connect)))
became:
Code:
(block peertube_peertube_1
(blockinherit container)
(blockinherit restricted_net_container)
(allow process process ( capability ( chown dac_override fowner fsetid kill net_bind_service setfcap setgid setpcap setuid sys_chroot )))
..
(allow process redis_port_t (tcp_socket (name_connect)))
...
)
After thatās done. You can stop the containers with podman compose down, load the .cil file into SELinux and try again.
Firewall
Fedora Server comes with a firewall and by default the PeerTube ports are not opened.
You will need to open the optional port 1935/TCP if youāre using PeerTubeās live feature and port 9000/TCP for PeerTube to work.
Code:
sudo firewall-cmd --permanent --add-port=1935/tcp
sudo firewall-cmd --permanent --add-port=9000/tcp
Running PeerTube
If your security policies & firewall are configured all thatās left to do is run
Code:
podman compose up
Congratulations on completing this step!
Persisting across reboots
I wanted to save the best part for the last section of this article.When the server reboots due to a power outage or something else the containers will be down. If that is yourdesired behaviour then you can skip this section.
You can generate Podman Quadlet files using podlet. The Quadlet filesare used to run containers using systemd.
Once installed you can run podlet compose
And it will generate .container files like this one:
Code:
# example generated redis.container
[Container]
Image=redis:6-alpine
PublishPort=6379:6379
[Service]
Restart=always
[Install] # added by me
WantedBy=default.target
Once the files are placed in any of the following directories systemd unit files will be generated out of them
Code:
/usr/share/containers/systemd/
/etc/containers/systemd/
$HOME/.config/containers/systemd/
The redis.container will generate a redis.service systemd unit file. Which can be placed in /usr/share/containers/systemd/ so that the container gets started on boot.
Of course generation of systemd unit files is still lacking and in our case weād want a network file too, podlet didnāt generate them for me and I had to write them manually. I also had to modify the existing ones, you can use them with copy-paste.
Make sure you donāt have any dangling containers & networks in podman either user mode or systemd mode or the setup will fail. I had a dangling network when Iāve used sudo podman compose up and had to remove it by running sudo podman network ls and sudo porman network rm 123.
You should create each file in the current directory
Code:
# peertube.network
[Unit]
Description=Peertube Network
[Network]
Subnet=173.18.0.42/16
Gateway=173.18.0.1
Label=app=peertube
# redis.container
[Container]
ContainerName=redis
ServiceName=redis
Image=redis:6-alpine
Network=peertube.network
[Service]
Restart=always
[Install]
WantedBy=default.target
# peertube.container
[Unit]
Requires=redis.service
After=redis.service
[Container]
ContainerName=peertube
EnvironmentFile=/home/dnutiu/peertube/.env # Note: you will need to replace the env file.
Image=chocobozzz/peertube:v7.0.0-bookworm
PublishPort=1935:1935
PublishPort=9000:9000
Volume=/mnt/peertube/data:/data
Volume=/mnt/peertube/config:/config
SecurityLabelType=peertube_peertube_1.process
Network=peertube.network
[Service]
Restart=always
[Install]
WantedBy=default.target
If now Iāve prepared a little script for installing and running the services either as user mode or root mode.
For root mode run:
Code:
sudo cp peertube.network /etc/containers/systemd/
sudo cp redis.container /etc/containers/systemd/
sudo cp peertube.container /etc/containers/systemd/
sudo systemctl daemon-reload
sudo systemctl stop peertube.service
sudo systemctl stop redis.service
sudo systemctl start redis.service
sudo systemctl start peertube.service
And for user mode:
Code:
mkdir -p $HOME/.config/containers/systemd/
cp peertube.network $HOME/.config/containers/systemd/
cp redis.container $HOME/.config/containers/systemd/
cp peertube.container $HOME/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user stop peertube.service
systemctl --user stop redis.service
systemctl --user start redis.service
systemctl --user start peertube.service
Once youāve run the script then, you can run podman ps or with sudo if you run in root mode.
And the good part is that this will persist across reboots.
Code:
dnutiu@legion:~/peertube$ sudo podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ee4f862d63f docker.io/library/redis:6-alpine redis-server About a minute ago Up About a minute 0.0.0.0:6379->6379/tcp systemd-redis
0e7a6e9871ed docker.io/chocobozzz/peertube:v7.0.0-bookworm node dist/server 29 seconds ago Up 29 seconds 0.0.0.0:1935->1935/tcp, 0.0.0.0:9000->9000/tcp peertube
Update 29.Ian: Adding PostgresSQL
I know that I said previously that I use PostgresSQL on another server. Iāve decided to move it on the Fedora Server as well,so I wanted to share with you the .cil file and .container file.I obtained these by referencing commands and the workflow from this article.
Code:
# cat postgres.cil
(block postgres
(blockinherit container)
(blockinherit restricted_net_container)
(allow process process ( capability ( chown dac_override fowner fsetid kill net_bind_service setfcap setgid setpcap setuid sys_chroot )))
(allow process default_t (file (link)))
(allow container_t default_t (dir (setattr)))
(allow process postgresql_port_t ( tcp_socket ( name_bind )))
(allow process default_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write )))
(allow process default_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write )))
(allow process default_t ( fifo_file ( getattr read write append ioctl lock open )))
(allow process default_t ( sock_file ( append getattr open read write )))
)
Code:
# cat postgres.container
[Unit]
Requires=redis.service
After=redis.service
[Container]
ServiceName=postgres
ContainerName=postgres
EnvironmentFile=/home/dnutiu/peertube/.env
Image=postgres:13-alpine
Volume=/data/postgres:/var/lib/postgresql/data
Network=peertube.network
SecurityLabelType=postgres.process
[Service]
Restart=always
[Install]
WantedBy=default.target
And of course you will need to update the environment file to have the db hostname setup correctly: PEERTUBE_DB_HOSTNAME=postgres.
Update 2.Feb: Backing up data
Backing up data for PeerTube can be done with a simple script that backups all the directories and their contents.
For my backup, Iāve created a simple script that does it like so:
Bash:
# cat backup.sh
name=$(date '+%Y-%m-%d')
cd /mnt/peertube
tar -zcvf "$name.config.tar.gz" config
tar -zcvf "$name.data.tar.gz" data
mv *.tar.gz /mnt/peertube/backups/
cd /data
systemctl stop postgres.service
tar -zcvf "$name.postgres.tar.gz" postgres
systemctl start postgres.service
mv *.tar.gz /mnt/peertube/backups/
And a systemd service
Code:
# cat peertube-backup.service
[Unit]
Description=peertube-backup
[Service]
Type=oneshot
User=root
ExecStart=/bin/bash /home/dnutiu/peertube/systemd/backup.sh
Now, to start the back-up service you can do it manually or use a systemd timer for automatic trigger of backup job.
Code:
# cat peertube-backup.timer
[Unit]
Description=peertube-backup
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
After that, all you need to do is install the backup and timer.
Code:
sudo cp peertube-backup.service /etc/systemd/system/
sudo cp peertube-backup.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable peertube-backup.timer
sudo systemctl start peertube-backup.timer
By checking the status of the timer you can see that it is enabled and when it will be triggered next.
Code:
sudo systemctl status peertube-backup.timer
ā peertube-backup.timer - peertube-backup
Loaded: loaded (/etc/systemd/system/peertube-backup.timer; enabled; preset: disabled)
Active: active (waiting) since Sun 2025-02-02 20:34:53 EET; 1s ago
Invocation: b7a6749243b9472798b50475853690e2
Trigger: Mon 2025-02-03 00:00:00 EET; 3h 25min left
Triggers: ā peertube-backup.service
Feb 02 20:34:53 systemd[1]: Started peertube-backup.timer - peertube-backup.
Conclusion
Weāve seen what it takes to run PeerTube using podman compose on the machine, how to use audit2allow in orderto troubleshoot SELinux issues and modify existing policies in order to allow PeerTube to work properly without gettingkilled by SELinux
In the end weāve transformed the docker-compose.yml file into systemd containers & networks files: redis.container,podman.container and podman.network which generated systemd unit files on their own.
Weāve also explored how to run those containers in user mode and root mode, and the most important thing is that theyauto-restart when a reboot occurs.

Thatās about it! Thank you for reading!

And a and happy new year!



