[Article] | November 10, 2025 | Updated: November 10, 2025
Linux Fedora adminsys server podman rootless docker FirewallD Cockpit

Fedora server base install + Podman rootless

A quick guide to get podman in rootless mode on a Fedora server

Fedora server base install + Podman rootless

Base Install

Log as root with ssh :

ssh root@<IP_or_Domain-name>

Set a root password

passwd

Upgrade the System

dnf upgrade --refresh

then reboot to apply kernel upgrade (if any) and relog as root

clean up your brand new fedora server

dnf autoremove

Create an non-root user (sudo)

set your username to a variable

export MYUSER=HERESETYOURUSERNAME
useradd -m -s /bin/bash -G wheel $MYUSER
passwd $MYUSER

wheel is Fedora’s default sudo group

update sshd config

create a custom config in /etc/ssh/sshd_config.d

vim /etc/ssh/sshd_config.d/01-non-root.conf

with this content :

PermitRootLogin no
AllowUsers <ADD YOUR USERNAME HERE>

PubkeyAuthentication yes

PasswordAuthentication no
PermitEmptyPasswords no

Add ssh public key for your user

mkdir /home/$MYUSER/.ssh
echo "<MY PUBLIC KEY>" >> /home/$MYUSER/.ssh/authorized_keys

chown -R $MYUSER:$MYUSER /home/$MYUSER/.ssh
chmod 700 /home/$MYUSER/.ssh
chmod 600 /home/$MYUSER/.ssh/authorized_keys

Restart SSH Service

keep your current root ssh session until your able to login with your non-root user

systemctl restart sshd.service

now open a new terminal and try to loggin

ssh <MYUSER>@<IP_or_Domain-name>

try if sudo is working with your user password

sudo dnf update --refresh

you can also try to log as root via sudo

sudo su root
id
exit

If everything is working you can now safely close your root session

optional packages

dnf install curl git nvim zsh ncdu

oh-my-zsh

see https://ohmyz.sh

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Podman

sudo dnf install podman podman-compose

https://podman.io/docs/installation#fedora

Rootless

https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md

test with a hello-world container (https://hub.docker.com/_/hello-world/):

podman run docker.io/hello-world

%% unlike docker you need to prefix image with registry ( eg. docker.io) %%

Output :

podman run docker.io/hello-world
Trying to pull docker.io/library/hello-world:latest...
Getting image source signatures
Copying blob 17eec7bbc9d7 done   |
Copying config 1b44b5a3e0 done   |
Writing manifest to image destination

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Portainer (Agent)

Rootless Podman socket
systemctl --user enable --now podman.socket

as user create a compose file $HOME/containers/portainer/docker-compose

mkdir -p $HOME/containers/portainer
vim $HOME/containers/portainer/docker-compose.yml

at the time i wrote this portainer LTS version is 2.33.1 https://docs.portainer.io/release-notes

services:
  agent:
    image: docker.io/portainer/agent:2.33.1
    container_name: portainer_agent
    ports:
      - "9001:9001"
    restart: always
    privileged: true
    security_opt:
      - label=disable
    volumes:
      - /run/user/<UID>/podman/podman.sock:/var/run/docker.sock:Z
      - /home/<USER>/.local/share/containers/storage/volumes:/var/lib/docker/volumes

Replace <UID> and <USER> with user id and your username (eg. 1000 and johndoe)

Then start portainer-agent service :

podman-compose -f $HOME/containers/portainer/docker-compose.yml up -d

check if portainer-agent is running with podman logs portainer_agent

Automaticaly start containers on server boot (persistent container)

enable podman-restart service for your user

systemctl --user enable --now podman-restart.service

and enable linger

loginctl enable-linger <MyUSER>

reboot to see if portainer-agent container persist between reboot

see https://docs.portainer.io/admin/environments/add/podman/socket for more informations

Priviledge Ports in rootless mode

if you want expose 80 and 443 for a web server in rootless-mode you have to redirect these ports to unpriviliged ports.

FirewallD (option 1 preferred on fedora)

install and enbable Firewalld service

sudo dnf install firewalld
sudo systemctl enable --now firewalld

by default only these service are not blocked (allowed) dhcpv6-client mdns ssh and i’m using my provider (hetzner) firewall so i will allow all incoming traffic with sudo firewall-cmd --set-default-zone=trusted keep in mind that if you are not behind another firewall like me this will allow everyone to access to exposed services.

changing the default zone with --set-default-zone=trusted is permanent and survives reboots.

Now add your redirect rules:

sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 --permanent
sudo firewall-cmd --add-forward-port=port=443:proto=tcp:toport=4443 --permanent
sudo firewall-cmd --reload

Verify the rules:

sudo firewall-cmd --list-forward-ports
sudo firewall-cmd --list-all

The --permanent flag makes the port forwarding rules persistent across reboots. The --reload command applies the permanent configuration to the running configuration.

Iptables (option 2 Debian/Ubuntu)

sudo vim /etc/systemd/system/redirect-port-80-443.service

[Unit]
Description=Redirect ports 80 to 8080 and 443 to 4443
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080'
ExecStart=/bin/bash -c 'iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 4443'
ExecStop=/bin/bash -c 'iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080'
ExecStop=/bin/bash -c 'iptables -t nat -D PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 4443'

[Install]
WantedBy=multi-user.target

then :

sudo systemctl daemon-reload

Test if it works

Check if it works : podman run --name nginx-test --restart always -d -p 8080:80 -p 4443:443 docker.io/nginx:alpine

Cockpit

for cockpit installation see https://cockpit-project.org/running.html#fedora

installation

sudo dnf install
sudo dnf install cockpit
jee
- 2026
version: 0.11.0 changelog code
Legal notice