Deploying an AngularJS app on DreamHost comes down to uploading static files: you build the app locally, copy the output into the domain’s web folder over SFTP, add an .htaccess file so deep links work, and turn on the free Let’s Encrypt certificate in the DreamHost panel. There is no Node process to run on the server because AngularJS (the 1.x line) executes entirely in the browser. That makes it one of the easiest frameworks to host on a shared plan.
/home/USER/example.com/, drop in an .htaccess with a rewrite rule that sends unknown paths to index.html if you use html5Mode, then enable HTTPS under Websites, then Secure Certificates in the panel. Add cache headers for hashed assets and you are done. Note that AngularJS reached end of life in January 2022, so treat this as maintaining a legacy app rather than starting a new one.This guide walks through a legacy AngularJS 1.x project on DreamHost Shared hosting. The same steps work on DreamHost VPS. At the end there is a short section on how a modern Angular project (version 2 and later) differs, because the two are often confused.
Before you start: AngularJS is end of life
AngularJS, meaning the 1.x framework loaded with a <script> tag and bootstrapped with ng-app, stopped receiving updates from Google on December 31, 2021. The team published the details on the official version support page. Since January 2022 there have been no security patches from the project. That does not stop the code from running, and thousands of internal tools still do, but it means two things for your deployment.
- Pin the exact
angular.jsversion you tested with. Do not loadlatestfrom a CDN, because there is no latest anymore and you want reproducible files. - Serve everything over HTTPS and set a Content Security Policy if the app handles anything sensitive, because the framework itself will not get fixes for browser level issues.
If you are starting a new project, use modern Angular, or one of the alternatives we covered in where you can deploy Vue.js. The hosting steps below are almost identical for any single page app.
Step 1: produce the deployable files
An AngularJS project is deployable in one of two shapes.
No build tool
Many older apps are just a folder with index.html, js/, css/, templates under views/, and vendor scripts. That folder is the deployable. Remove anything you do not want public (.git, sample data with real records) and move on to Step 2.
Grunt, Gulp or Webpack
If the project uses a task runner, run its production task and deploy the output directory only. The names vary by project, but the common patterns are:
npm install
# one of the following, check package.json "scripts"
npm run build
grunt build
gulp build
npx webpack --mode productionLook for a dist/ or build/ folder afterward. Old projects often need an older Node version to build; install nvm and run nvm install 14 or nvm install 10 to match what the project’s .nvmrc expects.
http://localhost:3000 strings are the number one reason a freshly uploaded AngularJS app shows an empty page on the live domain.Step 2: find the web folder and create an SFTP user
On DreamHost, each domain is served from a folder in the home directory of the user that owns it. The default path is /home/USERNAME/example.com/, and you can confirm or change it under Websites, then Manage Websites, then the domain’s Manage button, in the Web Directory field.
To upload you need a user with SFTP or shell access. In the panel go to Users, then Manage Users. Edit the user that owns the domain and set the type to Shell user if you want ssh and rsync, or SFTP user if you only want file transfer. DreamHost disables plain FTP by default on new accounts, and you should leave it disabled.
| Setting | Value |
|---|---|
| Host | Your server name from the panel (for example iad1-shared-b7-01.dreamhost.com) or the domain itself once DNS points at DreamHost |
| Port | 22 |
| Protocol | SFTP (SSH File Transfer Protocol) |
| Remote directory | /home/USERNAME/example.com/ |
| Auth | Password, or an SSH key added under the user’s settings |
Step 3: upload the files
With FileZilla or Cyberduck, connect with the details above, open the domain folder, delete the placeholder files DreamHost put there, and drag your app contents in. The index.html must end up directly inside the domain folder, not in a subfolder named dist.
From a terminal, rsync over SSH is faster for repeat deploys because it only sends changed files and removes files you deleted locally:
rsync -avz --delete ./dist/ USERNAME@example.com:/home/USERNAME/example.com/The trailing slash after dist/ matters. Without it rsync creates a dist folder on the server. Wrap that line in a tiny deploy.sh and you have a one command release. If you would rather push from a git remote or a CI job, the approach in our guide to launching Gatsby on Vultr translates directly, since a Gatsby build is also just static output.
Step 4: add .htaccess for html5Mode routing
AngularJS routes with either hash URLs (/#/users/42) or, when $locationProvider.html5Mode(true) is set, clean URLs (/users/42). Hash URLs need nothing from the server. Clean URLs do, because when a visitor loads /users/42 directly, Apache looks for a file at that path, finds nothing, and returns a 404 before AngularJS ever runs.
DreamHost shared hosting runs Apache with mod_rewrite enabled, so create a file named .htaccess in the domain folder with this content:
RewriteEngine On
RewriteBase /
# serve real files and folders as they are
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# everything else goes to the app shell
RewriteRule ^ index.html [L]Also make sure your index.html has <base href="/"> in the <head>, which html5Mode requires so that relative template and asset paths resolve from the root regardless of the current route. If the app lives in a subfolder such as /app/, set RewriteBase /app/, the base href to /app/, and the final rule to RewriteRule ^ /app/index.html [L].
Step 5: enable HTTPS with Let’s Encrypt
DreamHost issues and renews Let’s Encrypt certificates for free from the panel. Go to Websites, then Secure Certificates, find the domain, click Add, choose Let’s Encrypt, and confirm. Issuance usually completes within a few minutes once DNS is pointing at DreamHost. Renewal is automatic.
Then force HTTPS. You can toggle it in the panel (Websites, then Manage Websites, then the domain, look for the HTTPS redirect setting), or add it at the top of the same .htaccess above the routing rules:
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]Then check that every external script and API call also uses HTTPS, because a single http:// script tag is blocked as mixed content.
Step 6: caching headers
Static hosting is fast, but only if browsers are allowed to cache. The rule of thumb for a single page app is: cache hashed assets for a long time, never cache index.html. DreamHost’s Apache honors mod_expires and mod_headers directives in .htaccess:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
<FilesMatch "index\.html$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
</FilesMatch>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
</IfModule>The one year rule is only safe if your build appends a content hash to file names (app.3f9c2a.js). If your project serves plain app.js, shorten those to a day or add a query string version to the script tags, otherwise returning visitors run stale code after every release.
views/ for a year unless they are hashed too. Stale templates cause errors that only returning users see.How modern Angular differs
If your project has an angular.json, TypeScript files and @angular/core in package.json, it is modern Angular, not AngularJS. The deployment target on DreamHost is the same (static files, same .htaccess), but the build is different:
ng build --configuration production --base-href /
# output lands in dist/PROJECT-NAME/browser/ on recent versions
rsync -avz --delete dist/PROJECT-NAME/browser/ USERNAME@example.com:/home/USERNAME/example.com/Modern Angular always uses clean URLs, so the rewrite rule is mandatory rather than optional. It also hashes asset file names by default, which makes the long cache rule safe. Server side rendering with Angular SSR needs Node on the server and is not a fit for DreamHost Shared; use a DreamHost VPS or DreamCompute, or a platform built for Node.
Troubleshooting
Blank white page after upload
Open the browser console. If you see 404s for js/app.js or similar, the files landed in a subfolder, or the base href does not match the folder. If you see a CORS or connection error, the API URL is still pointing at localhost. Rebuild with the production API address.
Deep links return a DreamHost 404 page
The .htaccess either did not upload (many SFTP clients hide dotfiles; enable Show hidden files) or has Windows line endings. Save it again as UTF-8 with Unix line endings and upload again. Confirm with ls -la over SSH.
Internal Server Error (500) immediately after adding .htaccess
A typo in a directive. Rename the file temporarily to confirm, then add rules back a block at a time. The Header directive fails if mod_headers is unavailable, so wrap it in <IfModule mod_headers.c>.
Old version keeps loading after a deploy
Browser cache. Verify with a hard refresh or a private window. If the new build appears there, your cache headers are working as designed and the fix is hashed file names. Also check that DreamHost’s optional server side caching is not enabled for the domain.
Certificate shows as pending for hours
Let’s Encrypt validation needs the domain’s A record to already resolve to DreamHost. Check DNS under Websites, then Manage Websites, then DNS, and wait for propagation before retrying.
Frequently asked questions
Do I need Node.js on DreamHost to run AngularJS?
No. AngularJS runs entirely in the visitor’s browser. Node is only used on your own machine for the build tooling, if the project has any. The server just needs to send static files, which is exactly what DreamHost Shared hosting does with Apache. A backend API, if you have one, is a separate deployment.
Can I host the API on DreamHost too?
You can host a PHP or Python (Passenger) API on Shared hosting, and a Node API on a VPS. Put it on a subdomain such as api.example.com and configure CORS, or place it under the same domain and adjust the rewrite rule so /api/ paths are not sent to index.html. Our FuelPHP hosting guide covers the PHP side.
Should I use hash URLs instead of html5Mode to avoid .htaccess?
You can. Hash routing needs no server configuration and works from any static host. The cost is uglier URLs and weaker SEO for public content. For an internal tool that is a fine trade. For a public site, use html5Mode with the rewrite rule shown above.
Is it safe to keep running an AngularJS app in 2026?
It runs, but it is unsupported. Keep it behind HTTPS, restrict it to authenticated users where possible, avoid rendering untrusted HTML, and plan a migration. Commercial extended support exists from third parties if the app cannot be replaced soon. New features should go into a supported framework.
Wrapping up
An AngularJS deployment on DreamHost is a static upload with three finishing touches: a rewrite rule for clean URLs, a free Let’s Encrypt certificate, and cache headers that are aggressive for hashed files and off for index.html. The whole process fits in a fifteen minute session once the build works locally.
Because the framework is end of life, use this setup to keep a legacy app healthy while you plan its replacement. The hosting side will carry over unchanged to modern Angular or any other single page framework.
About this article: GeekBlog covers U.S. technology news, AI, phones, smartwatches and gaming. Every story is written and checked under our Editorial Policy. Spotted a mistake or have a story tip? Contact our editors.

