{"id":5713,"date":"2026-10-08T22:20:09","date_gmt":"2026-10-09T02:20:09","guid":{"rendered":"https:\/\/underhost.com\/blog\/?p=5713"},"modified":"2026-10-08T22:20:40","modified_gmt":"2026-10-09T02:20:40","slug":"install-emdash-cms-on-cpanel-and-shared-hosting-2026","status":"publish","type":"post","link":"https:\/\/underhost.com\/blog\/install-emdash-cms-on-cpanel-and-shared-hosting-2026\/","title":{"rendered":"Install EmDash CMS on cPanel and Shared Hosting (2026)"},"content":{"rendered":"<p><!-- UnderHost Blog Hero --><\/p>\n<div class=\"uh-blog-hero\" style=\"margin:0 0 40px;text-align:center;padding:48px 24px;border-radius:20px;background:linear-gradient(135deg,#0D1F3C 0%,#125A8A 58%,#176EA5 100%);color:#ffffff;box-shadow:0 20px 40px -15px rgba(13,31,60,0.28);position:relative;overflow:hidden;\">\n<div style=\"display:inline-flex;align-items:center;gap:8px;padding:7px 14px;margin-bottom:16px;border:1px solid rgba(0,212,255,0.32);border-radius:999px;color:#DFF8FF;font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;background:rgba(0,212,255,0.10);\"><i class=\"fas fa-download\" style=\"color:#00D4FF;\"><\/i> EmDash Install Guide<\/div>\n<h1 style=\"color:#ffffff;font-size:clamp(32px,5vw,46px);line-height:1.12;margin:0 0 14px;font-weight:800;\">How to Install EmDash CMS on cPanel, UnderHost Shared Hosting, and Servers Without a Panel<\/h1>\n<p style=\"font-size:18px;color:#EAF6FF;max-width:800px;margin:0 auto;line-height:1.7;\">Step-by-step install for a cPanel server, UnderHost shared hosting without SSH, and a Linux server without a panel, with the checks EmDash&#8217;s own docs require.<\/p>\n<\/div>\n<div class=\"uh-answer-box\" style=\"display:grid;grid-template-columns:auto 1fr;gap:18px;align-items:center;background:#ffffff;border:1px solid rgba(0,212,255,0.35);border-radius:16px;padding:22px;margin:0 0 34px;box-shadow:0 8px 28px rgba(13,31,60,0.10);\">\n<div style=\"font-size:clamp(26px,5vw,38px);font-weight:800;color:#125A8A;line-height:1.1;white-space:nowrap;\">Node.js 22.16+<\/div>\n<div style=\"color:#1F2937;line-height:1.7;\"><strong style=\"color:#0D1F3C;\">Short answer:<\/strong> EmDash needs <strong>Node.js 22.16 or later<\/strong>, a build step, a process that keeps running, a persistent folder for the database and uploads, and environment variables. All three paths below use the same build. They differ in how the process is started and whether you have SSH.<\/div>\n<\/div>\n<p><!-- Lead Summary --><\/p>\n<div class=\"uh-blog-excerpt\" style=\"border-left:4px solid #00D4FF;padding:18px 20px;margin:0 0 34px;background:#F8FAFC;color:#1F2937;border-radius:0 14px 14px 0;box-shadow:0 8px 28px rgba(13,31,60,0.08);line-height:1.75;\"><strong style=\"color:#0D1F3C;\">Main takeaway:<\/strong> Pick the path that matches your account. On UnderHost shared hosting, use the cPanel Node.js app path. On a cPanel server, the same steps apply, and SSH is optional. On any Linux server without a panel, you run the build and the process over SSH. Each path ends with the same checks, which come from EmDash&#8217;s deployment docs.<\/div>\n<div class=\"uh-post-content\" style=\"color:#1F2937;font-size:16px;line-height:1.75;\">\n<nav class=\"uh-toc\" aria-label=\"Table of contents\" style=\"background:#ffffff;border:1px solid #E5E7EB;border-radius:16px;padding:20px 22px;margin:0 0 34px;box-shadow:0 4px 12px rgba(13,31,60,0.08);\">\n<div style=\"font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#176EA5;margin-bottom:10px;\"><i class=\"fas fa-list\" style=\"color:#00D4FF;\"><\/i> In this guide<\/div>\n<ol style=\"margin:0;padding-left:20px;columns:2 260px;column-gap:28px;line-height:1.9;\">\n<li><a href=\"#paths\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Choose your install path<\/a><\/li>\n<li><a href=\"#local\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Step 0: build the project locally<\/a><\/li>\n<li><a href=\"#common\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Steps every path shares<\/a><\/li>\n<li><a href=\"#cpanel\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Path 1: cPanel server or shared hosting (Node.js App)<\/a><\/li>\n<li><a href=\"#shared\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Path 2: UnderHost shared hosting without SSH<\/a><\/li>\n<li><a href=\"#nopanel\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Path 3: Linux server without a panel<\/a><\/li>\n<li><a href=\"#checks\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Checks before you send traffic<\/a><\/li>\n<li><a href=\"#backups\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Backups<\/a><\/li>\n<li><a href=\"#updates\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Updating EmDash<\/a><\/li>\n<li><a href=\"#errors\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Errors and fixes<\/a><\/li>\n<li><a href=\"#cloudflare\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">Alternative: Cloudflare Workers<\/a><\/li>\n<li><a href=\"#faq\" style=\"color:#176EA5;text-decoration:none;font-weight:600;\">FAQ<\/a><\/li>\n<\/ol>\n<\/nav>\n<h2 id=\"paths\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-map\" style=\"color:#176EA5;\"><\/i> Choose Your Install Path<\/h2>\n<div style=\"overflow-x:auto;margin:26px 0;border:1px solid #E5E7EB;border-radius:14px;-webkit-overflow-scrolling:touch;\">\n<table style=\"width:100%;min-width:760px;border-collapse:collapse;background:#ffffff;color:#1F2937;font-size:15px;line-height:1.55;\">\n<caption style=\"caption-side:top;text-align:left;padding:12px 14px;font-size:13px;color:#6B7280;\">Install paths for EmDash, compared<\/caption>\n<thead>\n<tr style=\"background:#0D1F3C;color:#ffffff;\">\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Path<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Best for<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">SSH needed?<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Where the build runs<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Process kept running by<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\"><a href=\"#cpanel\" style=\"color:#176EA5;font-weight:600;text-decoration:underline;text-underline-offset:2px;\">Path 1: cPanel server or shared hosting<\/a><\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">cPanel accounts with Node.js App<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">No, but helpful<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Your computer or the app manager<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">cPanel Node.js App (Passenger)<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\"><a href=\"#shared\" style=\"color:#176EA5;font-weight:600;text-decoration:underline;text-underline-offset:2px;\">Path 2: UnderHost shared hosting<\/a><\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">UnderHost shared plans, testing and small sites<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">No<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Your computer (recommended) or app manager<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">cPanel Node.js App; may idle<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\"><a href=\"#nopanel\" style=\"color:#176EA5;font-weight:600;text-decoration:underline;text-underline-offset:2px;\">Path 3: Linux server, no panel<\/a><\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">VPS or dedicated server with root<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Yes<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">The server<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">systemd, pm2 or Docker<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Cloudflare Workers (alternative)<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">No server to manage<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">No (Wrangler on your computer)<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Your computer<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Cloudflare Workers<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p style=\"margin:0 0 18px;\">For production sites with scheduled publishing, a server where you control the process (Path 3, or a Cloud VPS) is the safer choice. Shared hosting is suitable for a test site or a small site that does not rely on scheduled posts.<\/p>\n<h2 id=\"local\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-code\" style=\"color:#00D4FF;\"><\/i> Step 0: Build the Project Locally<\/h2>\n<p style=\"margin:0 0 18px;\">Build and test the site on your own computer first. EmDash&#8217;s Node.js guide starts with the scaffolder, and the same project works on every path below.<\/p>\n<ul style=\"margin:0 0 24px;padding-left:22px;\">\n<li><strong>Check Node.js:<\/strong> run <code>node --version<\/code>. It must report v22.16.0 or later.<\/li>\n<li><strong>Create the project:<\/strong> run <code>npm create emdash@latest<\/code>. When asked where you will deploy, choose Node.js. Choose the Starter template, which the docs show with Posts and Pages.<\/li>\n<li><strong>Run it locally:<\/strong> run <code>npm run dev<\/code>, then open <code>http:\/\/localhost:4321\/_emdash\/admin\/<\/code> and complete the setup wizard.<\/li>\n<li><strong>Generate the encryption key:<\/strong> run <code>npx emdash secrets generate<\/code> and save the output. It encrypts plugin secrets. Keep a separate backup of it, because the docs say you cannot recover stored plugin secrets without it.<\/li>\n<li><strong>Set the site URL:<\/strong> set <code>EMDASH_SITE_URL<\/code> to your public address, for example <code>https:\/\/example.com<\/code>. It must be set at build time, or images are served unoptimised.<\/li>\n<\/ul>\n<div style=\"background:#FFF7ED;border:1px solid #FDBA74;border-radius:16px;padding:20px 22px;margin:24px 0;\">\n<h3 style=\"margin:0 0 10px;color:#9A3412;font-size:20px;\"><i class=\"fas fa-exclamation-triangle\" style=\"color:#F97316;\"><\/i> Do not upload your .env file:<\/h3>\n<p style=\"margin:0;color:#7C2D12;line-height:1.7;\">The scaffolder writes the encryption key to a .env file. Keep .env out of uploads and out of version control. Set the same variables in your hosting panel or server environment instead.<\/p>\n<\/div>\n<h2 id=\"common\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-list\" style=\"color:#176EA5;\"><\/i> Steps Every Path Shares<\/h2>\n<p style=\"margin:0 0 18px;\">These requirements come from EmDash&#8217;s Node.js deployment guide. They apply to every path.<\/p>\n<div style=\"overflow-x:auto;margin:26px 0;border:1px solid #E5E7EB;border-radius:14px;-webkit-overflow-scrolling:touch;\">\n<table style=\"width:100%;min-width:820px;border-collapse:collapse;background:#ffffff;color:#1F2937;font-size:15px;line-height:1.55;\">\n<caption style=\"caption-side:top;text-align:left;padding:12px 14px;font-size:13px;color:#6B7280;\">EmDash runtime requirements, and where each one is set<\/caption>\n<thead>\n<tr style=\"background:#0D1F3C;color:#ffffff;\">\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Requirement<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Setting<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Notes from the docs<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Node.js 22.16 or later<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Node version in the host, or your server<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Required. Check the version before you start.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Build step<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">npm run build, with EMDASH_SITE_URL set<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Produces dist\/server\/entry.mjs.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Start command<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">node .\/dist\/server\/entry.mjs<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Standalone Node entry. It does not read a .env file, so set variables in the environment.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Encryption key<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">EMDASH_ENCRYPTION_KEY<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Required for plugin secrets. Generate with npx emdash secrets generate.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Database<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">DATABASE_PATH, for example \/home\/you\/emdash\/data\/emdash.db<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">SQLite needs persistent disk and write access to the folder.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Uploads<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Local directory .\/data\/uploads, or S3\/R2 storage<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Back up the upload folder with the database.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Address and port<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">HOST and PORT (default 4321)<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">On a panel, the app manager may assign the port. Follow its instructions.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">HTTPS<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Reverse proxy, panel SSL, or Cloudflare<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Set EMDASH_SITE_URL so absolute URLs are correct.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h2 id=\"cpanel\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-server\" style=\"color:#00D4FF;\"><\/i> Path 1: cPanel Server or Shared Hosting (Node.js App)<\/h2>\n<p style=\"margin:0 0 18px;\">Use this path on a cPanel account with a Setup Node.js App tool. The menu labels below follow common cPanel wording. Your screen may differ, so match the steps to the fields you see.<\/p>\n<ul style=\"list-style:none;margin:0 0 24px;padding:20px 22px;background:#F8FAFC;border:1px solid rgba(23,110,165,0.14);border-radius:16px;line-height:1.7;\">\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Create the app.<\/strong> In Setup Node.js App, choose Create Application. Set the Node.js version to 22.16 or later. Set the application root to a folder such as <code>emdash<\/code>. Set the application URL to your domain or subdomain.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Set the startup file.<\/strong> Set it to <code>dist\/server\/entry.mjs<\/code>, which EmDash&#8217;s docs start with <code>node<\/code>. If the manager rejects an .mjs file, ask UnderHost support whether it can run an ES module, and test before going further.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Upload the project.<\/strong> Upload your project folder through File Manager as a zip, then extract it in the application root. Do not upload node_modules or .env. Upload dist\/ only if you build on your computer.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Install and build.<\/strong> Use Run NPM Install in the app manager if it is offered, then run the build. If the app manager cannot run the build, build on your computer and upload dist\/ and the packages it needs (see the note below).<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Set environment variables.<\/strong> Add EMDASH_ENCRYPTION_KEY, EMDASH_SITE_URL and DATABASE_PATH in the app manager. Add HOST if the manager asks for it. Do not set PORT yourself unless the manager tells you to, because it assigns the port.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Create the data folders.<\/strong> In File Manager, create the folder for the database and the uploads folder. Make sure the app can write to them.<\/li>\n<li style=\"margin:0 0 0;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Start the app.<\/strong> Restart it from the app manager. Then open your domain and check the checks in the section below.<\/li>\n<\/ul>\n<div style=\"border-left:4px solid #00D4FF;padding:18px 20px;margin:24px 0;background:#F8FAFC;border-radius:0 14px 14px 0;line-height:1.75;\"><strong style=\"color:#0D1F3C;\">Build notes for cPanel:<\/strong> A build on a shared server can hit memory or time limits. Building on your computer avoids that. The packages in node_modules must work on the server&#8217;s Linux system, so if a native package fails, use the install step on the server instead. We have not tested either build route on UnderHost, so check the results before you rely on them.<\/div>\n<h2 id=\"shared\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-shield-alt\" style=\"color:#176EA5;\"><\/i> Path 2: UnderHost Shared Hosting Without SSH<\/h2>\n<p style=\"margin:0 0 18px;\">This is the same app-manager route as Path 1, with shared-plan limits. UnderHost shared plans include Node.js and crontab and do not include SSH, so you do everything in cPanel and File Manager.<\/p>\n<ul style=\"margin:0 0 24px;padding-left:22px;\">\n<li><strong>Build on your computer.<\/strong> Without SSH, the build is the step most likely to fail on shared hosting. Build with <code>npm run build<\/code> on your computer, then upload dist\/ and the runtime packages.<\/li>\n<li><strong>Test the process.<\/strong> Check whether the app stays running between visits. EmDash&#8217;s docs say scheduled publishing pauses when no process runs, so test a scheduled post before you rely on it.<\/li>\n<li><strong>Keep the data small.<\/strong> Shared plans have disk and bandwidth limits, and the SQLite file and uploads grow with content. Check your plan&#8217;s disk limit before you upload media.<\/li>\n<li><strong>Back up through File Manager.<\/strong> Download the database file and the uploads folder regularly. Restores need the process stopped, as the docs say.<\/li>\n<\/ul>\n<div style=\"background:#FFF7ED;border:1px solid #FDBA74;border-radius:16px;padding:20px 22px;margin:24px 0;\">\n<h3 style=\"margin:0 0 10px;color:#9A3412;font-size:20px;\"><i class=\"fas fa-exclamation-triangle\" style=\"color:#F97316;\"><\/i> When to move:<\/h3>\n<p style=\"margin:0;color:#7C2D12;line-height:1.7;\">If the app goes idle, your scheduled posts do not run, or the build fails, move the site to a Cloud VPS (Path 3). Shared hosting is a reasonable place to test EmDash. Production with scheduled posts needs a process that stays up.<\/p>\n<\/div>\n<h2 id=\"nopanel\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-server\" style=\"color:#00D4FF;\"><\/i> Path 3: Linux Server Without a Panel<\/h2>\n<p style=\"margin:0 0 18px;\">Use this path on a VPS or dedicated server with root or sudo access and no control panel, such as a fresh Ubuntu, Debian, AlmaLinux or Rocky Linux server. The commands below come from the EmDash Node.js guide. The process-manager step is general Linux practice, not part of EmDash&#8217;s docs.<\/p>\n<ul style=\"margin:0 0 24px;padding-left:22px;\">\n<li><strong>Install Node.js 22.16 or later.<\/strong> Use your distribution&#8217;s packages or a Node.js version manager. Confirm with <code>node --version<\/code>.<\/li>\n<li><strong>Copy the project to the server.<\/strong> Use git, scp or sftp. Work in a directory your app user owns, for example <code>\/var\/www\/emdash<\/code>.<\/li>\n<li><strong>Install and build.<\/strong> Run <code>npm ci<\/code> and then <code>npm run build<\/code>, with <code>EMDASH_SITE_URL<\/code> set in the environment first.<\/li>\n<li><strong>Set the environment.<\/strong> Put EMDASH_ENCRYPTION_KEY, EMDASH_SITE_URL, DATABASE_PATH, HOST and PORT in the service environment. The standalone Node entry does not read a .env file.<\/li>\n<li><strong>Start the server.<\/strong> Run <code>node .\/dist\/server\/entry.mjs<\/code> to test it. Then keep it running with a service manager.<\/li>\n<li><strong>Put a proxy in front.<\/strong> Use Nginx, Caddy or your panel&#8217;s proxy to serve HTTPS on your domain and forward to the EmDash port. Set EMDASH_SITE_URL to the public HTTPS address.<\/li>\n<\/ul>\n<h2 id=\"nopanel-systemd\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-cog\" style=\"color:#176EA5;\"><\/i> Keeping the Process Running<\/h2>\n<p style=\"margin:0 0 18px;\">EmDash&#8217;s docs say scheduled tasks run inside the Node process, so the process must stay up. On a server with systemd, a service file keeps it running and restarts it after a crash or reboot. The example below is general systemd practice and has not been tested with EmDash. Replace the paths and user with yours, and test it on a staging server first.<\/p>\n<pre style=\"background:#0D1F3C;color:#EAF6FF;padding:18px 20px;border-radius:14px;overflow-x:auto;line-height:1.7;font-size:15px;margin:0 0 24px;\"><code>[Unit]\r\nDescription=EmDash CMS\r\nAfter=network.target\r\n\r\n[Service]\r\nUser=emdash\r\nWorkingDirectory=\/var\/www\/emdash\r\nEnvironmentFile=\/etc\/emdash\/emdash.env\r\nExecStart=\/usr\/bin\/node .\/dist\/server\/entry.mjs\r\nRestart=always\r\n\r\n[Install]\r\nWantedBy=multi-user.target<\/code><\/pre>\n<p style=\"margin:0 0 18px;\">Docker is also documented by EmDash. The docs include a Dockerfile that builds on node:22-alpine and a Compose file with a named volume for \/app\/data. Use it on a server where Docker is already set up.<\/p>\n<h2 id=\"checks\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-check\" style=\"color:#00D4FF;\"><\/i> Checks Before You Send Traffic<\/h2>\n<p style=\"margin:0 0 18px;\">These checks come from EmDash&#8217;s docs, which say to keep a new instance out of traffic until every applicable check passes. The migration check needs a terminal, so run it on your computer or a server with SSH. On shared hosting without SSH, the first request applies migrations automatically, and the admin test shows whether it worked.<\/p>\n<ul style=\"list-style:none;margin:0 0 24px;padding:20px 22px;background:#F8FAFC;border:1px solid rgba(23,110,165,0.14);border-radius:16px;line-height:1.7;\">\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Request \/health<\/strong> and one public page. Both must return a successful response. Create the health route before the build, at <code>src\/pages\/health.ts<\/code>, returning OK with status 200.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Run the migration check<\/strong> from the built project with <code>npx emdash migrate --check<\/code>, if you have a terminal. It must report no pending or unknown migrations.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Sign in to \/_emdash\/admin\/<\/strong>, create a disposable draft, publish it and confirm the public page changes.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Upload a test media file<\/strong>, open its URL, then delete it.<\/li>\n<li style=\"margin:0 0 10px;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Test a scheduled post<\/strong> if you rely on scheduled publishing, and confirm it goes live.<\/li>\n<li style=\"margin:0 0 0;padding-left:28px;position:relative;\"><i class=\"fas fa-check-circle\" style=\"color:#00D4FF;position:absolute;left:0;top:5px;\"><\/i> <strong>Check sandboxed plugins,<\/strong> if you use them. Invoke one plugin route and confirm the log has no sandbox or startup error.<\/li>\n<\/ul>\n<p style=\"margin:0 0 18px;\">The health route only proves that the Node process can serve pages. It does not prove that the database, storage or plugin sandbox is healthy, so run the other checks as well.<\/p>\n<h2 id=\"backups\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-shield-alt\" style=\"color:#176EA5;\"><\/i> Backups<\/h2>\n<p style=\"margin:0 0 18px;\">EmDash&#8217;s docs say to back up both the SQLite file and the upload directory, and to stop the process before replacing either during recovery. Keep a copy of EMDASH_ENCRYPTION_KEY separately, because the docs say that restoring a database without the key leaves plugin secrets unreadable.<\/p>\n<ul style=\"margin:0 0 24px;padding-left:22px;\">\n<li><strong>Shared hosting and panels:<\/strong> download the database file and uploads folder from File Manager on a schedule.<\/li>\n<li><strong>Servers:<\/strong> copy the database and uploads with your normal backup tools, and keep at least one copy off the server.<\/li>\n<li><strong>Restore:<\/strong> stop the process, replace the files, then start it again and run the checks.<\/li>\n<\/ul>\n<h2 id=\"updates\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-sync\" style=\"color:#00D4FF;\"><\/i> Updating EmDash<\/h2>\n<p style=\"margin:0 0 18px;\">EmDash&#8217;s update guide says to update the emdash and @emdash-cms\/cloudflare packages in one step, because they share a version and the Cloudflare package depends on the exact matching version. Plugin packages have their own versions and declare the minimum EmDash version they need. Back up before any update.<\/p>\n<ul style=\"margin:0 0 24px;padding-left:22px;\">\n<li><strong>Read the release notes.<\/strong> A major release can require changes to your project.<\/li>\n<li><strong>Update, build and restart.<\/strong> Update the package, run the build again with EMDASH_SITE_URL set, then restart the app.<\/li>\n<li><strong>Check the site.<\/strong> Run the checks above again before you send traffic.<\/li>\n<li><strong>Template files do not update automatically.<\/strong> Compare your layouts and configuration with the current template yourself.<\/li>\n<\/ul>\n<h2 id=\"errors\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-bug\" style=\"color:#176EA5;\"><\/i> Errors and Fixes<\/h2>\n<p style=\"margin:0 0 18px;\">The table lists errors that EmDash&#8217;s docs describe. We have not found documented fixes for cPanel-specific errors, so those are marked as not documented.<\/p>\n<div style=\"overflow-x:auto;margin:26px 0;border:1px solid #E5E7EB;border-radius:14px;-webkit-overflow-scrolling:touch;\">\n<table style=\"width:100%;min-width:760px;border-collapse:collapse;background:#ffffff;color:#1F2937;font-size:15px;line-height:1.55;\">\n<caption style=\"caption-side:top;text-align:left;padding:12px 14px;font-size:13px;color:#6B7280;\">Errors and fixes<\/caption>\n<thead>\n<tr style=\"background:#0D1F3C;color:#ffffff;\">\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Symptom<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Where<\/th>\n<th scope=\"col\" style=\"padding:14px;text-align:left;\">Fix from the docs<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">ExperimentalWarning: SQLite<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Node 22<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Expected. It does not stop the database from opening.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Plugin secrets cannot be saved or read<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Any Node install<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Check EMDASH_ENCRYPTION_KEY is set and valid. Generate one with npx emdash secrets generate.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Images are not optimised<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Build<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Set EMDASH_SITE_URL before npm run build.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Scheduled posts do not publish<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Any Node install<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Keep at least one Node process running. The scheduler pauses when no process runs.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">D1 or R2 binding not found<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Cloudflare<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Check the binding names in wrangler.jsonc match the EmDash configuration (DB and MEDIA in the template).<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Migration or schema errors<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Cloudflare<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Run wrangler tail and reproduce the error to capture the logs.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">App does not start on cPanel<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">cPanel app manager<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Not documented by EmDash. Check the startup file path, Node version and the app log in the app manager. Ask UnderHost support if the log is unclear.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\" style=\"padding:14px;border-top:1px solid #E5E7EB;text-align:left;color:#0D1F3C;background:#F8FAFC;\">Build fails on shared hosting<\/th>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">cPanel shared<\/td>\n<td style=\"padding:14px;border-top:1px solid #E5E7EB;\">Not documented by EmDash. Build on your computer, then upload dist\/.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h2 id=\"cloudflare\" style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:34px 0 14px;scroll-margin-top:90px;\"><i class=\"fas fa-cloud\" style=\"color:#176EA5;\"><\/i> Alternative: Cloudflare Workers<\/h2>\n<p style=\"margin:0 0 18px;\">If you do not want to run a server, EmDash documents a Cloudflare route with Workers, D1 for the database and R2 for media. You log in with Wrangler on your computer, build, and deploy. The site then runs on Cloudflare, not on your hosting account.<\/p>\n<ul style=\"margin:0 0 24px;padding-left:22px;\">\n<li>Run <code>pnpm wrangler login<\/code>, then <code>pnpm build<\/code>, then <code>pnpm wrangler deploy<\/code>. The first deploy creates the D1 database and R2 bucket.<\/li>\n<li>The template includes a Cron Trigger for scheduled publishing and maintenance.<\/li>\n<li>Point your domain to the Worker in Cloudflare, and set SSL in your Cloudflare zone.<\/li>\n<\/ul>\n<p style=\"margin:0 0 18px;\">Use the Cloudflare route when you want no server to manage. Keep your hosting account for other sites, and remember that the EmDash site and its data then live on Cloudflare.<\/p>\n<div class=\"uh-section-divider\" aria-hidden=\"true\" style=\"width:min(100% - 32px, 1080px);margin:44px auto;display:grid;grid-template-columns:1fr 32px 1fr;align-items:center;gap:18px;pointer-events:none;\">\n  <span style=\"height:1px;background:linear-gradient(90deg,transparent,rgba(0,212,255,0.40),rgba(23,110,165,0.24),transparent);\"><\/span><br \/>\n  <img src=\"https:\/\/cdn.underhost.com\/android-chrome-192x192.webp\" width=\"32\" height=\"32\" alt=\"\" loading=\"lazy\" decoding=\"async\" style=\"width:32px;height:32px;display:block;border-radius:8px;filter:drop-shadow(0 0 14px rgba(0,212,255,0.30));\"><br \/>\n  <span style=\"height:1px;background:linear-gradient(90deg,transparent,rgba(23,110,165,0.24),rgba(0,212,255,0.40),transparent);\"><\/span>\n<\/div>\n<div class=\"uh-blog-cta\" style=\"background:linear-gradient(135deg,#0D1F3C 0%,#125A8A 58%,#176EA5 100%);color:#ffffff;padding:36px 24px;border-radius:20px;text-align:center;margin:44px 0;box-shadow:0 20px 40px -15px rgba(13,31,60,0.32);\">\n<h2 style=\"margin:0 0 12px;font-size:28px;line-height:1.25;color:#ffffff;\">Need a Server That Keeps EmDash Running?<\/h2>\n<p style=\"font-size:17px;margin:0 auto 22px;color:#EAF6FF;max-width:720px;line-height:1.7;\">A Cloud VPS gives you Node.js 22.16 or later, a process that stays up, and root access for backups and updates. Start with a test site, then move production when the checks pass.<\/p>\n<p>  <a href=\"https:\/\/underhost.com\/cloud-vps.php\" style=\"background:linear-gradient(90deg,#00D4FF,#0077FF);color:#ffffff;padding:13px 28px;border-radius:10px;text-decoration:none;font-weight:800;display:inline-block;margin:8px;box-shadow:0 6px 18px rgba(0,212,255,0.25);\">View Cloud VPS Plans<\/a><a href=\"https:\/\/underhost.com\/shared-hosting.php\" style=\"background:transparent;color:#ffffff;padding:12px 28px;border-radius:10px;text-decoration:none;font-weight:800;display:inline-block;margin:8px;border:1px solid rgba(255,255,255,0.32);\">Compare Shared Hosting<\/a><a href=\"https:\/\/customerpanel.ca\/client\/\" style=\"background:transparent;color:#ffffff;padding:12px 28px;border-radius:10px;text-decoration:none;font-weight:800;display:inline-block;margin:8px;border:1px solid rgba(255,255,255,0.32);\">Ask @CustomerPanel<\/a>\n<\/div>\n<div class=\"uh-faq-section\" id=\"faq\" style=\"margin:34px 0;scroll-margin-top:90px;\">\n<h2 style=\"color:#0D1F3C;font-size:28px;line-height:1.25;margin:0 0 18px;border-bottom:2px solid rgba(0,212,255,0.22);padding-bottom:10px;\">Frequently Asked Questions<\/h2>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">Can I install EmDash on cPanel?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">Yes, if the cPanel account has Node.js 22.16 or later and a Setup Node.js App tool. Use the cPanel path in this guide. Confirm the Node.js version first, because EmDash will not run on an older version.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">Do I need SSH to install EmDash?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">No, not for the cPanel path. The app manager runs the server, and environment variables are set in cPanel. You do need a way to run the build: either the app manager&#8217;s install step, or building on your own computer and uploading the output. SSH makes the build and the checks easier on a server without a panel.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">Can I install EmDash on UnderHost shared hosting?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">Yes, using the cPanel Node.js app path, on a plan with Node.js 22.16+. Shared hosting has memory and process limits, and a process that goes idle can pause scheduled publishing. Use a Cloud VPS for a production site with scheduled posts.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">What Node.js version does EmDash need?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">Node.js 22.16.0 or later, as stated in the EmDash deployment docs and the package engines field. Node 22 prints an ExperimentalWarning about SQLite. The docs say the warning does not stop the database from opening.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">How do I create the admin account?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">Open \/_emdash\/admin\/ on your site. A new site redirects to the setup wizard. Enter a site title and your email, then register a passkey in the browser. The setup wizard runs once.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">Where is my content stored?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">On a Node.js install with SQLite, content is in the database file set by DATABASE_PATH or the config, and uploads are in the upload directory. Back up both, and stop the process before restoring either.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">What if scheduled posts do not publish?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">EmDash&#8217;s docs say the scheduler runs only while a Node.js process is running, and pauses when every process stops or sleeps. Keep at least one process running in production. On shared hosting, test a scheduled post to see whether the app stays up.<\/p>\n<\/p><\/div>\n<div style=\"margin-top:18px;background:#F8FAFC;padding:18px 20px;border-radius:14px;border:1px solid rgba(23,110,165,0.14);\">\n<h3 style=\"color:#0D1F3C;margin:0 0 8px;font-size:19px;\">Can I install EmDash on Cloudflare instead?<\/h3>\n<p style=\"margin:0;color:#1F2937;line-height:1.7;\">Yes. Cloudflare Workers with D1 and R2 is a documented route that needs no server shell, because you deploy with Wrangler from your own computer. The site then runs on Cloudflare, not on your cPanel account.<\/p>\n<\/p><\/div>\n<\/div>\n<p><!-- FAQPage schema (generated from the visible FAQ above) --><br \/>\n<script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can I install EmDash on cPanel?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes, if the cPanel account has Node.js 22.16 or later and a Setup Node.js App tool. Use the cPanel path in this guide. Confirm the Node.js version first, because EmDash will not run on an older version.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Do I need SSH to install EmDash?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"No, not for the cPanel path. The app manager runs the server, and environment variables are set in cPanel. You do need a way to run the build: either the app manager's install step, or building on your own computer and uploading the output. SSH makes the build and the checks easier on a server without a panel.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can I install EmDash on UnderHost shared hosting?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes, using the cPanel Node.js app path, on a plan with Node.js 22.16+. Shared hosting has memory and process limits, and a process that goes idle can pause scheduled publishing. Use a Cloud VPS for a production site with scheduled posts.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What Node.js version does EmDash need?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Node.js 22.16.0 or later, as stated in the EmDash deployment docs and the package engines field. Node 22 prints an ExperimentalWarning about SQLite. The docs say the warning does not stop the database from opening.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do I create the admin account?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Open \/_emdash\/admin\/ on your site. A new site redirects to the setup wizard. Enter a site title and your email, then register a passkey in the browser. The setup wizard runs once.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Where is my content stored?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"On a Node.js install with SQLite, content is in the database file set by DATABASE_PATH or the config, and uploads are in the upload directory. Back up both, and stop the process before restoring either.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What if scheduled posts do not publish?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"EmDash's docs say the scheduler runs only while a Node.js process is running, and pauses when every process stops or sleeps. Keep at least one process running in production. On shared hosting, test a scheduled post to see whether the app stays up.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can I install EmDash on Cloudflare instead?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. Cloudflare Workers with D1 and R2 is a documented route that needs no server shell, because you deploy with Wrangler from your own computer. The site then runs on Cloudflare, not on your cPanel account.\"\n      }\n    }\n  ]\n}\n<\/script>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A step-by-step install guide for EmDash CMS on three targets: a cPanel server, UnderHost shared hosting without SSH, and a Linux server without a panel. Covers Node.js 22.16+, build steps, environment variables, checks, backups and updates.<\/p>\n","protected":false},"author":1,"featured_media":5710,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,77,81,106,47],"tags":[],"class_list":["post-5713","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articles","category-cloudflare","category-hosting-guides","category-how-to-guides","category-software"],"_links":{"self":[{"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/posts\/5713","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/comments?post=5713"}],"version-history":[{"count":1,"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/posts\/5713\/revisions"}],"predecessor-version":[{"id":5714,"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/posts\/5713\/revisions\/5714"}],"wp:attachment":[{"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/media?parent=5713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/categories?post=5713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/underhost.com\/blog\/wp-json\/wp\/v2\/tags?post=5713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}