diff --git a/modules/action-first-run.php b/modules/action-first-run.php
new file mode 100644
index 0000000..790fd6a
--- /dev/null
+++ b/modules/action-first-run.php
@@ -0,0 +1,145 @@
+<?php
+register_module([
+	"name" => "First Run Interface",
+	"version" => "0.1",
+	"author" => "Starbeamrainbowlabs",
+	"description" => "Provides the first-run interface some thigns might be a be skew-whiff if you don't go through the first-run interface, but if you know what you're doing you shouldn't need this module. Currently in development.",
+	"id" => "action-first-run",
+	"optional" => true,
+	"code" => function() {
+		global $settings;
+		
+		// Force the user to the first-run interface
+		if(!$settings->setup_complete)
+			$env->action = "first-run";
+		
+		/**
+		 * @api {get} ?action=first-run		Show the first-run interface
+		 * @apiName Hash
+		 * @apiGroup Utility
+		 * @apiPermission Anonymous
+		 */
+		
+		/*
+		 * ███████ ██ ██████  ███████ ████████    ██████  ██    ██ ███    ██
+		 * ██      ██ ██   ██ ██         ██       ██   ██ ██    ██ ████   ██
+		 * █████   ██ ██████  ███████    ██ █████ ██████  ██    ██ ██ ██  ██
+		 * ██      ██ ██   ██      ██    ██       ██   ██ ██    ██ ██  ██ ██
+		 * ██      ██ ██   ██ ███████    ██       ██   ██  ██████  ██   ████
+		 */
+		add_action("first-run", function() {
+			global $settings, $paths;
+			
+			$stage = intval($_GET["stage"] ?? 0);
+			$stage_count = 4; // The number of setup stages
+			
+			switch($stage) {
+				case 0:
+					
+					$peppermint_config_url = dirname(full_url()) . "/peppermint.json";
+					$config_checker = curl_init($peppermint_config_url);
+					curl_setopt($config_checker, CURL_HEADER, true);
+					curl_setopt($config_checker, CURL_NOBODY, true);
+					curl_setopt($config_checker, CURL_RETURNTRANSFER, 1);
+					curl_setopt($config_checker, CURL_TIMEOUT, 5);
+					curl_exec($config_checker);
+					
+					$peppermint_config_returnstatus = intval(curl_getinfo($config_checker, CURLINFO_HTTP_CODE));
+					
+					if($peppermint_config_returnstatus >= 200 &&
+						$peppermint_config_returnstatus < 300) {
+						http_response_code(500);
+						
+						if(!rename($paths->settings_file, "$paths->settings_file.compromised")) {
+							exit(page_renderer::render_minimal("Configuration Error - Pepperminty Wiki", "<h1>0: Configuration Error</h1>
+							<p>Welcome to Pepperminty Wiki! Unforutnately, your setup doesn't appear to be quite right, as not only is your new <code>peppermint.json</code> configuration file exposed to the internet (causing your site's secret to be divulged), but Pepperminty Wiki doesn't appear to have write access to rename it either.</p>
+							<p>You might need to check the permissions on the directory you've copied Pepperminty Wiki to.</p>
+							<p>Once you've fixed these issues, simply delete the created <code>peppermint.json</code> file and reload this page.</p>"));
+						}
+						
+						exit(page_renderer::render_minimal("Security Error - Pepperminty Wiki", "<h1>0: Security Error</h1>
+						<p>Welcome to Pepperminty Wiki! Unforutnately, your setup doesn't appear to be quite right, as your the new <code>peppermint.json</code> configuration file for your brand-new Pepperminty Wiki instance appears to be accessible from the internet. This means that anyone could get a hold of your site secret and password hashes! To protect your installation, it's been moved to <code>peppermint.json.compromised</code> - and you'll need to delete (or move it) out of the way to continue.</p>
+						<p>Please block access from the internet to this file - Pepperminty Wiki reads it directly from disk.</p>"));
+					}
+					
+					$content = "<h1>0: Begin!</h1>";
+					$content .= "<p>Welcome to Pepperminty Wiki! This page is a first-run page that will be shown just this once (if you want to access it again, visit the <code>first-run</code> action), and will guide you through the setup of your new Pepperminty Wiki instance.</p>
+					<p>To get started, enter the site secret into the box below to prove that you own the site. It was can found in the <code>peppermint.json</code> file that Pepperminty Wiki has just created, under the name <code>secret</code>.</p>
+					<p>Security check: &#10004; - <code>peppermint.json</code> doesn't appear to be accessible form the internet (though it doesn't hurt to check yourself)</p>
+					<form method='POST' action='?action=first-run&stage=1'>
+						<label for='secret'>Site Secret:</label>
+						<input type='text' id='secret' name='secret' placeholder='e.g. 170cc5fdef9075a0d9510e3' />
+						<input type='submit' value='Continue &raquo;' />
+					</form>";
+					
+					break;
+				
+				case 1:
+					if(empty($_POST["secret"]) || $_POST["secret"] !== $settings->secret)
+						exit(page_renderer::render_main("Error - Setup - Pepperminty Wiki", "<p>That site secret doesn't appear to match what's stored in <code>pepperminty.json</code>. <a href='?action=first-run&stage=0'>Go back</a>.</p>"));
+					
+					$content .= "<h1>1: Get Ready!</h1>
+					<p>Cool! Now that we've got you verified, let's get started! Fill out the form below to start to customise your Pepperminty Wiki instance.</p>
+					<form method='POST' action='?action=first-run&stage=2'>
+						<label><h3>Wiki name:</h3></label>
+						<p>The name of your wiki.</p>
+						<input type='text' id='sitename' name='sitename' value='e.g. CrossCode Wiki' />
+						
+						<h3>Administrator Account</h3>
+						<p>It's time to create your very first account! This account is special - it's your administrator account (you can promote more users to be administrators by editing <code>peppermint.json</code> after completing this setup). The username must not contain spaces - they'll be stripped out if you include them!</p>
+						
+						<label for='admin-username'>Username:</label>
+						<input type='text' id='admin-username' name='admin-username' placeholder='e.g. jebediah' />
+						
+						<p>Your email address. Users will be invited to contact you with this address if they experience issues.</p>
+						<label for='admin-email'>Email address:</label>
+						<input type='email' id='admin-email' name='admin-email' />
+						
+						<p>The password for your new account. Make sure it's secure!</p>
+						<label for='password'>Password:</label>
+						<input type='password' id='password' name='password' />
+						<br />
+						<label for='password-repeat'>Repeat Password:</label>
+						<input type='password' id='password-repeat' name='password-repeat' />
+						
+						<br />
+						<input type='submit' value='Continue &raquo;' />
+					</form>";
+					
+					break;
+				
+				case 2:
+					if($_GET["password"] !== $_GET["password-repeat"])
+						exit(page_renderer::render_minimal("Password mismatch - Pepperminty Wiki", "<p>Those passwords don't seem to match! <a href='?action=first-run&stage=0'>Go back</a>.</p>"));
+					
+					$admin_username = $_GET["admin-username"];
+					$admin_email = $_GET["admin-email"];
+					
+					// Set the sitename
+					$settings->sitename = $_GET["sitename"];
+					// Set the admin details
+					$settings->admindetails_name = $admin_username;
+					$settings->admindetails_email = $admin_email;
+					// Setup a new users table
+					$settings->users = [
+						$admin_username => [
+							"email" => $admin_email,
+							"password" => hash_password($_GET["password"])
+						]
+					];
+					// Save the new settings
+					file_put_contents($paths->settings_file, json_encode($settings, JSON_PRETTY_PRINT));
+					
+					$content .= "<p>Brilliant! You're practically all set. There's just some small step to complete though: Pepperminty Wiki needs to download a few resources from the internet. To do this, Pepperminty Wiki will need access to the following domains:</p>";
+					
+					$content .= "<p>If you're not sure what this means, then the server $settings->sitename is running on is probably already configured correctly.</p>";
+					break;
+					
+			}
+			
+			exit(page_renderer::render_minimal("Setup [ $stage / $stage_count ] - $settings->sitename", $content));
+		});
+	}
+]);
+
+?>
diff --git a/peppermint.guiconfig.json b/peppermint.guiconfig.json
index 0d26540..95499e1 100644
--- a/peppermint.guiconfig.json
+++ b/peppermint.guiconfig.json
@@ -3,7 +3,8 @@
 	"defaultpage": {"type": "text", "description": "The name of the page that will act as the home page for the wiki. This page will be served if you don't specify a page.", "default": "Main Page"},
 	"admindetails_name": {"type": "text", "description": "Your name as the wiki administrator.", "default": "Administrator"},
 	"admindetails_email": {"type": "email", "description": "Your email address as the wiki administrator. Will be displayed as a support contact address.", "default": "admin@localhost"},
-	"favicon": {"type": "url", "description": "A url that points to the favicon you want to use for your wiki. This image  By default this is set to a data: url of a Peppermint (Credit: by bluefrog23, source: https://openclipart.org/detail/19571/peppermint-candy-by-bluefrog23)", "default": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB3VBMVEXhERHbKCjeVVXjb2/kR0fhKirdHBziDg6qAADaHh7qLy/pdXXUNzfMAADYPj7ZPDzUNzfbHx/fERHpamrqMTHgExPdHx/bLCzhLS3fVFTjT0/ibm7kRkbiLi7aKirdISHeFBTqNDTpeHjgERHYJCTVODjYQkLaPj6/AADVOTnpbW3cIyPdFRXcJCThMjLiTU3ibW3fVVXaKyvcERH4ODj+8fH/////fHz+Fxf4KSn0UFD/CAj/AAD/Xl7/wMD/EhL//v70xMT/+Pj/iYn/HBz/g4P/IyP/Kyv/7Oz0QUH/9PT/+vr/ior/Dg7/vr7/aGj/QED/bGz/AQH/ERH/Jib/R0f/goL/0dH/qan/YWH/7e3/Cwv4R0f/MTH/enr/vLz/u7v/cHD/oKD/n5//aWn+9/f/k5P/0tL/trb/QUH/cXH/dHT/wsL/DQ3/p6f/DAz/1dX/XV3/kpL/i4v/Vlb/2Nj/9/f/pKT+7Oz/V1f/iIj/jIz/r6//Zmb/lZX/j4//T0//Dw/4MzP/GBj/+fn/o6P/TEz/xMT/b2//Tk7/OTn/HR3/hIT/ODj/Y2P/CQn/ZGT/6Oj0UlL/Gxv//f3/Bwf/YmL/6+v0w8P/Cgr/tbX0QkL+9fX4Pz/qNzd0dFHLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfeCxINNSdmw510AAAA5ElEQVQYGQXBzSuDAQCA8eexKXOwmSZepa1JiPJxsJOrCwcnuchBjg4O/gr7D9zk4uAgJzvuMgcTpYxaUZvSm5mUj7TX7ycAqvoLIJBwStVbP0Hom1Z/ejoxrbaR1Jz6nWinbKWttGRgMSSjanPktRY6mB9WtRNTn7Ilh7LxnNpKq2/x5LnBitfz+hx0qxUaxhZ6vwqq9bx6f2XXvuUl9SVQS38NR7cvln3v15tZ9bQpuWDtZN3Lgh5DWJex3Y+z1KrVhw21+CiM74WZo83DiXq0dVBDYNJkFEU7WrwDAZhRtQrwDzwKQbT6GboLAAAAAElFTkSuQmCC"},
+	"setup_complete": {"type": "checkbox", "description": "Whether the first-run tutorial has been completed or not.", "default": false}
+	"favicon": {"type": "url", "description": "A url that points to the favicon you want to use for your wiki. By default this is set to a data: url of a Peppermint (Credit: by bluefrog23, source: https://openclipart.org/detail/19571/peppermint-candy-by-bluefrog23)", "default": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB3VBMVEXhERHbKCjeVVXjb2/kR0fhKirdHBziDg6qAADaHh7qLy/pdXXUNzfMAADYPj7ZPDzUNzfbHx/fERHpamrqMTHgExPdHx/bLCzhLS3fVFTjT0/ibm7kRkbiLi7aKirdISHeFBTqNDTpeHjgERHYJCTVODjYQkLaPj6/AADVOTnpbW3cIyPdFRXcJCThMjLiTU3ibW3fVVXaKyvcERH4ODj+8fH/////fHz+Fxf4KSn0UFD/CAj/AAD/Xl7/wMD/EhL//v70xMT/+Pj/iYn/HBz/g4P/IyP/Kyv/7Oz0QUH/9PT/+vr/ior/Dg7/vr7/aGj/QED/bGz/AQH/ERH/Jib/R0f/goL/0dH/qan/YWH/7e3/Cwv4R0f/MTH/enr/vLz/u7v/cHD/oKD/n5//aWn+9/f/k5P/0tL/trb/QUH/cXH/dHT/wsL/DQ3/p6f/DAz/1dX/XV3/kpL/i4v/Vlb/2Nj/9/f/pKT+7Oz/V1f/iIj/jIz/r6//Zmb/lZX/j4//T0//Dw/4MzP/GBj/+fn/o6P/TEz/xMT/b2//Tk7/OTn/HR3/hIT/ODj/Y2P/CQn/ZGT/6Oj0UlL/Gxv//f3/Bwf/YmL/6+v0w8P/Cgr/tbX0QkL+9fX4Pz/qNzd0dFHLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfeCxINNSdmw510AAAA5ElEQVQYGQXBzSuDAQCA8eexKXOwmSZepa1JiPJxsJOrCwcnuchBjg4O/gr7D9zk4uAgJzvuMgcTpYxaUZvSm5mUj7TX7ycAqvoLIJBwStVbP0Hom1Z/ejoxrbaR1Jz6nWinbKWttGRgMSSjanPktRY6mB9WtRNTn7Ilh7LxnNpKq2/x5LnBitfz+hx0qxUaxhZ6vwqq9bx6f2XXvuUl9SVQS38NR7cvln3v15tZ9bQpuWDtZN3Lgh5DWJex3Y+z1KrVhw21+CiM74WZo83DiXq0dVBDYNJkFEU7WrwDAZhRtQrwDzwKQbT6GboLAAAAAElFTkSuQmCC"},
 	"logo_url": {"type": "url", "description": "A url that points to the site's logo. Leave blank to disable. When enabled the logo will be inserted next to the site name on every page.", "default": "//starbeamrainbowlabs.com/images/logos/peppermint.png"},
 	"logo_position": {"type": "text", "description": "The side of the site name at which the logo should be placed.", "default": "left"},
 	"show_subpages": {"type": "text", "description": "Whether to show a list of subpages at the bottom of the page.", "default": true},
diff --git a/settings.fragment.php b/settings.fragment.php
index 85a9328..7d35e94 100644
--- a/settings.fragment.php
+++ b/settings.fragment.php
@@ -21,6 +21,12 @@ GUICONFIG;
 
 $settingsFilename = "peppermint.json";
 
+if(file_exists("$settingsFilename.compromised")) {
+	http_response_code(500);
+	header("content-type: text/plain");
+	exit("Error: $settingsFilename.compromised exists on disk, so it's likely you need to block access to 'peppermint.json' from the internet. If you've done this already, please delete $settingsFilename.compromised and reload this page.");
+}
+
 $guiConfig = json_decode($guiConfig);
 $settings = new stdClass();
 if(!file_exists($settingsFilename))
