Back to Article List

Upgrade Pi-hole from v5 to v6 on a server

Upgrade Pi-hole from v5 to v6 on a server

Updated and tested 18 October 2026

pihole -up does the migration. What it does not do is clean up everything the v5 install left behind, and that is where the forum threads come from. On a Debian 12 or Ubuntu 24.04 server the command itself takes a few minutes; the rest of this page is the hour after it, when lighttpd is still installed, the files you kept in /etc/dnsmasq.d/ stop being read and the password you remember is sitting in a file the new version no longer opens.

The project calls the v5 to v6 migration a one-way operation in the v6 release announcement of 18 February 2025, and that single fact sets the order below: export first, upgrade second, clean up third. At the time of writing that means FTL v6.8, Core v6.5 and Web v6.6.1.

Export with Teleporter before you run pihole -up

I think a Teleporter export before pihole -up is the one step not to skip, because the migration is one-way and the archive is the only thing that brings lists, groups and clients back if the new install goes wrong. In the v5 web interface it sits under Settings > Teleporter and comes out as a .tar.gz; the same archive from the command line is pihole -a -t. Download it to your own machine, not to the server you are about to change.

Then copy the two directories the installer is going to touch:

sudo tar czf ~/pihole-v5-$(date +%F).tar.gz /etc/pihole /etc/dnsmasq.d

The v6 side of this, the archive format and the pihole-FTL --teleporter export that replaced pihole -a -t, is in the Pi-hole v6 Teleporter backup article. For the upgrade itself the v5 export is what matters. If your provider offers a VPS snapshot, take one too; there is no supported downgrade, so the snapshot is the rollback.

Run the update

Check what is waiting first, which the Updating Pi-hole page does not mention: the --check-only flag stops the script before any Pi-hole component is updated. It still rebuilds and installs the dependency package on the way, so expect a few apt lines first.

sudo pihole -up --check-only

pihole -up --check-only on Pi-hole v6: Core, Web Interface and FTL up to date, Everything is up to date

The check run reports each component and changes no Pi-hole component.

Each component reports update available or up to date. The docs page itself is short and most of it is this warning:

Ensure you read the release notes for all Pi-hole components. This will help you avoid common problems due to known issues with upgrading or newly required arguments. [...] This is especially recommended for major updates like v5 -> v6.

Read the Core and FTL notes, then run the update:

sudo pihole -up

The installer notices a v5 install by the presence of /etc/pihole/setupVars.conf and runs the migration path. While it installs the new scripts it moves 01-pihole.conf, 02-pihole-dhcp.conf, 04-pihole-static-dhcp.conf, 05-pihole-custom-cname.conf and 06-rfc6761.conf out of /etc/dnsmasq.d/ into /etc/pihole/migration_backup_v6/, renames /etc/dnsmasq.conf to /etc/dnsmasq.conf.old and removes the pihole-admin.conf include from the lighttpd config.

Then, if lighttpd is running, a dialog titled "Pi-hole v6.0 no longer uses lighttpd" appears. Its text says v6 "has its own embedded web server so lighttpd is no longer needed *unless* you have custom configurations", and that if you opt out of disabling it, "pihole-FTL will try to bind to an alternative port such as 8080". Say yes. When the terminal isn't interactive the installer assumes yes. Either way lighttpd is stopped and disabled, not uninstalled, which matters in a minute.

After that it prints "Migrating Pi-hole configuration to version 6". That line is pihole-FTL migrate v6 doing the work: it reads setupVars.conf and pihole-FTL.conf, moves both into the same backup directory, imports the upstreams, the listening mode, the interface, the password hash, DNSSEC, the reverse servers, your static DHCP leases, custom CNAMEs and custom.list, picks the web ports and writes /etc/pihole/pihole.toml.

What is different on disk after the upgrade

One file holds the configuration now, and how pihole.toml works in Pi-hole v6 has the full behaviour; the short version is that FTL owns the file and rewrites it. Everything you used to set in setupVars.conf, pihole-FTL.conf or the web interface is a key in pihole.toml, and the way to change it is sudo pihole-FTL --config key value.

FTL also generates /etc/pihole/dnsmasq.conf on every start. Its header warns that FTL overwrites it whenever the configuration changes. If you edited 01-pihole.conf in v5, that habit ends here.

Anything you dropped into /etc/dnsmasq.d/ yourself is now ignored. The Docker upgrade page states it plainly: "By default, Pi-hole v6 no longer reads configuration files from /etc/dnsmasq.d/." The switch that turns it back on is misc.etc_dnsmasq_d:

sudo pihole-FTL --config misc.etc_dnsmasq_d true

Two things to know before you flip it. After the 6.1 release, server=/domain/ip lines in that directory stopped working for a number of users even with the option on; discourse thread 80309 traces it to a change in how the local domain is handled, and the developers answered it with the dns.domain.local key, so start there if a conditional-forwarding line goes missing after an update. And since FTL v6.7.1 the related key misc.dnsmasq_lines became read-only for the API and the web interface, after a report that dnsmasq directives such as dhcp-script name programs dnsmasq executes. Files under /etc/dnsmasq.d/ have the same reach. Treat write access to that directory as root access to the box.

Still have a custom.list from v5? Your local DNS records moved as well. v5 kept them in /etc/pihole/custom.list; v6 imports that file into the dns.hosts array and from then on writes its own copy to /etc/pihole/hosts/custom.list. Add new entries with sudo pihole-FTL --config dns.hosts or under Settings > Local DNS Records, never by editing the generated file.

Fix the web interface after the upgrade

During migration FTL probes ports 80 and 443. If something holds them it falls back to 8080 and 8443 and logs a line starting with Config initialized with webserver ports in /var/log/pihole/FTL.log. On a server that ran nothing but Pi-hole the ports stay at 80 and 443 and the interface is at http://10.100.0.1/admin/ over the WireGuard tunnel, or at the server's address on your LAN.

The common failure is a 403 or the old PHP login page. Discourse thread 76307 collected twenty-odd replies on exactly this in the week after release, and the cause is lighttpd still serving: the dialog was answered no, or the disable step did not take. The fix is to remove the package Pi-hole no longer needs:

systemctl status lighttpd
sudo apt remove lighttpd
sudo systemctl restart pihole-FTL

One more check, because the port decision is made once: if lighttpd was still holding port 80 when the migration ran, FTL wrote 8080 and 8443 into webserver.port in pihole.toml, and removing lighttpd afterwards does not change that. sudo pihole-FTL --config webserver.port shows the value; the reset that a Pi-hole developer gave in that thread is sudo pihole-FTL --config webserver.port "80o,443os,[::]:80o,[::]:443os". The other causes of a dead admin page, from a Host header mismatch to a login page that keeps reloading, are listed under pi.hole/admin not working. If you pinned a different port in v5 and want it kept, set webserver.port; reinstalling lighttpd is the wrong fix.

Log in with the password you had. The migration imports WEBPASSWORD from setupVars.conf, and if the login refuses it, sudo pihole setpassword sets a new one. The old pihole -a -p no longer exists.

Command changes from v5 to v6

Most of the pihole script survived. The entries below are the ones that did not, with the v6 form you type instead. Apart from pihole -c, a removed command gives no hint on v6: pihole -a -p, -a -t, -w, -b, restartdns and arpflush all print the generic Usage: pihole [options] help.

v5v6Note
pihole -a -ppihole setpasswordInteractive, or pass the password in single quotes
pihole -w example.compihole allow example.com-d removes, -l lists
pihole -b example.compihole deny example.comSame options as allow
pihole restartdnspihole reloaddnsFlushes the cache and reloads lists; does not re-read config files. A full restart is sudo systemctl restart pihole-FTL
pihole -a -tpihole-FTL --teleporterWrites a zip into the current directory and prints its name; v5 produced a .tar.gz
pihole -cRemovedPrints Chronometer is gone, use PADD (https://github.com/pi-hole/PADD)
pihole arpflushpihole networkflush --arpThe old name has been removed from the script
Edit setupVars.confpihole-FTL --config key valueKeys are documented in the FTL configuration reference
Edit /etc/pihole/custom.listpihole-FTL --config dns.hostsFTL regenerates /etc/pihole/hosts/custom.list
WEBPASSWORD (Docker)FTLCONF_webserver_api_passwordAny setting set by environment variable becomes read-only

Scripts that called pihole -w or pihole -b from cron fail after the upgrade, so grep your crontabs and any Ansible roles for the old flags. The rest of the v6 CLI, including pihole api <endpoint> for talking to the new REST API without curl, is listed by pihole -h.

Your idea deserves better hosting

24/7 support 30-day money-back guaranteeRefund covers the VPS plan on your first order. Cancel anytime
Platební období

VPS.S1

$5.99 Save  17 %
$4.99 Měsíčně
  • 2 vCPU AMD EPYC
  • 2 GB RAMPAMĚŤ
  • 30 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně

VPS.S3

$14.99 Save  33 %
$9.99 Měsíčně
  • 4 vCPU AMD EPYC
  • 6 GB RAMPAMĚŤ
  • 70 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně

VPS.S4

$19.99 Save  20 %
$15.99 Měsíčně
  • 6 vCPU AMD EPYC
  • 8 GB RAMPAMĚŤ
  • 80 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně

EPYC VPS.P1

$8.99 Save  22 %
$6.99 Měsíčně
  • 2 vCPU AMD EPYC
  • 4 GB RAMPAMĚŤ
  • 40 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

EPYC VPS.P2

$16.99 Save  24 %
$12.99 Měsíčně
  • 2 vCPU AMD EPYC
  • 8 GB RAMPAMĚŤ
  • 80 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

EPYC VPS.P4

$29.99 Save  23 %
$22.99 Měsíčně
  • 4 vCPU AMD EPYC
  • 16 GB RAMPAMĚŤ
  • 160 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

EPYC VPS.P5

$39.99 Save  25 %
$29.99 Měsíčně
  • 8 vCPU AMD EPYC
  • 16 GB RAMPAMĚŤ
  • 180 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

EPYC VPS.P6

$59.99 Save  25 %
$44.99 Měsíčně
  • 8 vCPU AMD EPYC
  • 32 GB RAMPAMĚŤ
  • 200 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

EPYC VPS.P7

$69.99 Save  29 %
$49.99 Měsíčně
  • 16 vCPU AMD EPYC
  • 32 GB RAMPAMĚŤ
  • 240 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

Genoa VPS.G2

$24.99 Save  20 %
$19.99 Měsíčně
  • 2 vCPUAMD EPYC Genoa 4. generace 9xx4 s 3,25 GHz nebo podobný, na architektuře Zen 4. AMD EPYC G4
  • 4 GB DDR5PAMĚŤ
  • 50 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

Genoa VPS.G4

$44.99 Save  22 %
$34.99 Měsíčně
  • 4 vCPUProcesor AMD EPYC s dedikovanými vCPU jádry, na serverovém hardwaru pro firmy. AMD EPYC G4
  • 8 GB DDR5PAMĚŤ
  • 100 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

Genoa VPS.G6

$89.99 Save  22 %
$69.99 Měsíčně
  • 8 vCPUProcesor AMD EPYC s dedikovanými vCPU jádry, na serverovém hardwaru pro firmy. AMD EPYC G4
  • 16 GB DDR5PAMĚŤ
  • 200 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

Genoa VPS.G7

$159.99 Save  22 %
$124.99 Měsíčně
  • 8 vCPUProcesor AMD EPYC s dedikovanými vCPU jádry, na serverovém hardwaru pro firmy. AMD EPYC G4
  • 32 GB DDR5PAMĚŤ
  • 250 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku. v ceně
  • Auto zálohy zdarmaZahrnuje jeden slot pro zálohu, který můžete nastavit na denní, týdenní nebo měsíční spouštění.

AMD Ryzen VPS.R1

$16.99 Save  18 %
$13.99 Měsíčně
  • 1 dedikované CPU AMD Ryzen 9 7950X s 4,5 GHz nebo podobný, na architektuře Zen 4. vCPU
  • 4 GB DDR5PAMĚŤ
  • 50 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6 v ceně Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku.
  • Auto zálohy v ceně

AMD Ryzen VPS.R2

$29.99 Save  17 %
$24.99 Měsíčně
  • 2 dedikovaná CPU AMD Ryzen 9 7950X s 4,5 GHz nebo podobný, na architektuře Zen 4. vCPU
  • 8 GB DDR5PAMĚŤ
  • 100 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6 v ceně Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku.
  • Auto zálohy v ceně

AMD Ryzen VPS.R4

$109.99 Save  18 %
$89.99 Měsíčně
  • 8 dedikovaná CPU AMD Ryzen 9 7950X s 4,5 GHz nebo podobný, na architektuře Zen 4. vCPU
  • 32 GB DDR5PAMĚŤ
  • 400 GB NVMeÚLOŽIŠTĚ
  • Neměřený provoz
  • IPv4 & IPv6 v ceně Podpora IPv6 není aktuálně dostupná ve Francii, Finsku ani Nizozemsku.
  • Auto zálohy v ceně

*VAT excluded.

INCLUDED WITH EVERY PLAN

✓ No setup fees ✓1 Gbps network
✓ Full root access on KVM ✓ Free server monitoring ✓ Firewall management ✓24/7 support

Docker containers

The last image with v5 components was 2024.07.0; every later tag is v6. The Docker v5 to v6 upgrade page carries the full rename table, and the pattern is one rule: every old variable becomes FTLCONF_<section>_<key>. PIHOLE_DNS_ is FTLCONF_dns_upstreams (semicolon-separated), DNSMASQ_LISTENING is FTLCONF_dns_listeningMode, INTERFACE is FTLCONF_dns_interface, WEB_PORT is FTLCONF_webserver_port. Variables such as DNS1, ServerIP, VIRTUAL_HOST and WEB_BIND_ADDR are dropped with no replacement.

If the host is a Docker VPS with other services on port 80, set FTLCONF_webserver_port before the first start. Keep the /etc/dnsmasq.d volume mounted for that first v6 start, with FTLCONF_misc_etc_dnsmasq_d: 'true', so the migration can read your old files; the comments in the official compose file say it can be removed afterwards. pihole checkout is disabled inside the official image, so a container moves between versions by image tag only.

Rollback

There is none the project supports. The announcement says the migration is one-way; the installer moves your v5 files into migration_backup_v6 and the gravity database is upgraded to a newer schema (version 16 in the v6.0 changelog). Restore the VPS snapshot, or on Docker pin pihole/pihole:2024.07.0 against a copy of the old volume. The v5 Teleporter archive imports into either; v6 also accepts the old .tar.gz through the web interface and the API, which import its tables and setupVars.conf and then restart FTL to migrate them.

Check the result

Two commands confirm the upgrade and one confirms you did not open a resolver to the internet. pihole -v prints the three component versions and the latest available ones, as in Core version is v6.5 (Latest: v6.5). pihole status prints "FTL is listening on port 53" with ticks for UDP and TCP, then "Pi-hole blocking is enabled".

pihole -v: Core version v6.5, Web version v6.6.1, FTL version v6.8, each with the latest available version

pihole -v prints each component with the latest available version.

The migration imports DNSMASQ_LISTENING into dns.listeningMode, so a server that was set to "Allow only local requests" in v5 keeps that. Check anyway, because an upgraded v5 box on a public address is the shape most open-resolver reports have:

sudo pihole-FTL --config dns.listeningMode
sudo ss -tulpn 'sport = :53'

On a VPS the mode should be SINGLE or LOCAL on the tunnel interface, as in the WireGuard-only VPS setup, and the firewall should still drop port 53 on the public interface. If the migration produced anything else, sudo pihole-FTL --config dns.listeningMode SINGLE fixes it and restarts FTL on its own. Then prove it from a machine outside the tunnel:

dig @YOUR_SERVER_IP example.com +time=3

That query has to time out. If it answers, the listening-mode and firewall cases in the Pi-hole error reference come before anything else on your list. Every minute an open resolver is up is a minute it can be used in an amplification attack against someone else.

Questions?

My Home Assistant Pi-hole integration stopped working after the v6 upgrade. What changed?

v6 removed the PHP API at /admin/api.php along with its API token, so any client written for v5 needs a v6-aware version. The Home Assistant Pi-hole integration supports v6 now and asks for an app password, which you create under Settings > Web interface / API with the Configure app password button (the settings level at the top right has to be on Expert for it to show). Scripts and other monitoring talk to the REST API under /api/: POST /api/auth returns a session ID, and later requests carry it in the X-FTL-SID header.

About the author

J. Brennan

Jack Brennan started as a field technician in New South Wales and later spent several years maintaining infrastructure in commercial data centres. Procedures and training material gradually became part of the job, and documentation followed from there.

He writes about bare-metal servers, storage, hardware troubleshooting and the practical side of moving data between physical and virtual environments. Installation guides are another regular subject, especially where assumptions about networking or server hardware can trip up somebody doing the job for the first time. Jack lives near Newcastle, Australia, with two "majestic" greyhounds. He has restored motorcycles since his 20s, particularly Japanese bikes from the 1980s, and volunteers backstage at a community theatre on lighting and set construction.

Deploy your next project in seconds

Bring your winning ideas online faster, with modern hardware and unmetered bandwidth. Join a European cloud trusted by thousands of developers and businesses worldwide.