Suchpanda, the new mascot of the kids search engine

Since July, our search engine for children lived at kids.findnix.eu, a subdomain of the general-purpose search engine findnix.eu. This month we moved it to its own name and its own domain: Suchpanda at suchpanda.de. This post explains why we split the two, and how we did the move without breaking a single old link, sitemap or admin tool.

Why a subdomain was the wrong home

A kids' search engine and an adult-capable general search engine can share a codebase and a database, but they should not share an identity. These were our reasons:

  • Different promises. findnix.eu has accounts, advertising packages, a points system, a domain marketplace and a user area for site owners. The kids site has none of that: no tracking, no ads, nothing a child has to type into an account form. Parents who see the same brand on both will reasonably wonder where the line between them is.
  • Different trust boundaries. Every filter, blocklist and reputation signal that applies to the parent can leak onto a subdomain, and the other way round. A children's service should not be one spam report away from being treated like the site it was spun off from.
  • Different rules for content. The kids index is curated and checked by hand: no war, no violence, no sex education, no dangerous experiments. The general index is open by design. Two sets of rules belong under two names.
  • A brand of its own. The kids site already had two mascots, Uli and Nele. It now has a third, the Suchpanda ("search panda"), and a name that says what it does ("such" = search) without carrying the parent's brand.
  • Clean operations. Public pages, robots rules, sitemaps and webmaster accounts are separate per domain. Giving the kids site its own domain means its own robots.txt, its own sitemaps and its own Search Console, Bing and Yandex properties.

The requirements for the move

  1. suchpanda.de is the canonical home; suchpanda.eu and kids.findnix.eu redirect to it.
  2. Every old URL keeps working through a 301, including paths and query strings.
  3. Admin tools that are called across domains must not be redirected. Our admin imports images and videos by calling two scripts on the old host with a shared key. They stay on kids.findnix.eu.
  4. No downtime, no broken sitemaps, no lost links in the database.

Step 1: domains and DNS

We registered both domains and pointed @ and www at the server. The .eu domain came up within minutes. The .de domain did not: the registry (DENIC) kept a placeholder nameserver entry (not.connected.suchpanda.de IN A 127.0.0.1) while the registrar's own nameservers already answered correctly for the zone. A quick look with whois -h whois.denic.de and dig against the nameservers showed that the zone was fine and the nameserver update had simply not reached the registry. The registrar fixed it on their side, and a few minutes later the domain resolved everywhere.

Useful checks that saved us hours of guessing:

# What does the registry say? whois -h whois.denic.de -- "-T dn suchpanda.de" # Does each nameserver answer authoritatively with the same zone? for ns in a.ns.example.net b.ns.example.net; do dig +norec SOA suchpanda.de @$ns | grep -c 'flags:.* aa' done 

Step 2: one vhost, three names

The kids site runs in its own PHP-FPM pool with an open_basedir limited to its own directory. Instead of copying the site, we added suchpanda.de and www.suchpanda.de as aliases of the existing web domain. That keeps one document root and one pool, and the Let's Encrypt certificate simply carries all three names:

v-add-web-domain-alias USER kids.findnix.eu suchpanda.de,www.suchpanda.de v-add-letsencrypt-domain USER kids.findnix.eu suchpanda.de,www.suchpanda.de 

suchpanda.eu became a separate, empty web domain with its own certificate and a forced 301 to https://suchpanda.de$request_uri.

Step 3: the redirect that keeps the admin tools alive

All traffic for the old host is redirected, except two admin scripts and the ACME challenge path (otherwise certificate renewals for the old name would loop):

set $sp_redir 0; if ($host = kids.findnix.eu) { set $sp_redir 1; } if ($host = www.suchpanda.de) { set $sp_redir 1; } if ($uri ~ "^/(admin-import-a|admin-import-b)\.php$") { set $sp_redir 0; } if ($uri ~ "^/\.well-known/acme-challenge/") { set $sp_redir 0; } if ($sp_redir) { return 301 https://suchpanda.de$request_uri; } 

It lives in a custom include next to the generated Hestia config, so it survives rebuilds. We tested it with curl before and after: the old host answers 301 for pages and 403 (no key) or 200 (with key) for the two admin scripts.

Step 4: code, data and sitemaps

The base URL of the kids app was one constant, but the old name was also hard-coded in about two dozen places. We wrote a small patch script with a dry run, per-file backups and a PHP lint pass, with rules to skip filesystem paths, because they must not change when only the public name does:

  • the kids base URL, the sitemap generators and robots.txt;
  • the constants that build public URLs for books, tasks and study aids in the admin;
  • 71 absolute links stored in the database (REPLACE() on https://kids.findnix.eu/ after a dump);
  • the footer button on the main site, the RSS feed and the sitemap lines in the main site's robots.txt.

One more detail came from Yandex: in our setup it did not pick up the sub-sitemaps through the sitemap index. So every one of the 129 sub-sitemaps is now listed individually in robots.txt, generated by a small cron job that reads the index every morning and rewrites the file only if it looks plausible and has changed.

What went wrong along the way

While adding the new vhost, Hestia restarted a PHP-FPM version, and the systemd unit refused to start: Failed to set up mount namespacing: Invalid argument (the sandbox option PrivateDevices=true does not work in this container environment). Three sites on that PHP version returned 502 for under a minute until we disabled the sandbox options with a systemd drop-in. We have since applied the same drop-in to every service that uses them, and we now check systemctl show php8.4-fpm -p PrivateDevices before any vhost operation. If you run Hestia in a container, this one is worth knowing.

Checklist if you are planning the same move

  • Redirect by host, not by path, and keep an explicit exception list for internal tools.
  • Keep the old host's robots.txt crawlable. If it is blocked, crawlers never see your 301s.
  • Add the new domain to Search Console, Bing Webmaster Tools and Yandex Webmaster, and submit the sitemaps. Leave the old property in place until you have used the site-move tool.
  • Reissue the certificate with all aliases once the new name resolves publicly, not before.
  • Migrate absolute URLs stored in the database, and keep dumps.
  • Expect consent banners to ask again: cookie consent is per domain.

Result

Suchpanda is live at suchpanda.de. The old URLs redirect, the admin imports still run, sitemaps and robots.txt use the new name, and the kids site finally has an identity that does not depend on its parent. If you want to see it, it is at suchpanda.de.