During development of a website, I often have the need to share the intermediate results with my clients using basic authentication. On one of my servers, I perform the following steps to get it up and running.
Publish the site
Assuming you have already created the website, build and deploy it to a folder that can be served by node.js
. In my case, I often use parcel
to build the client side, using something along the following lines as part of the package.json
. As I don't want to hard-code the backend server's location in my client code, it is written in an .env
file, e.g.
cat packages/gui/.env
SERVER="http://xxx.xxx.xxx.xxx/bob"
And in my GUI code, I reference process.env.SERVER
, which Parcel will replace with the value found in the .env
file.
If you use TypeScript, you also need to add a declaration file for this to work, e.g. env.d.ts
declare const process: { env: { SERVER: string } };
To actually do the build process, I have something like this in my package.json
(and rimraf
and parcel-bundler
are part of my devDependencies
), so I can use npm run build:domain
to deploy the site:
"scripts": {
"start": "parcel index.html",
"clean": "rimraf ./public ./.cache ./dist",
"build": "parcel build index.html --out-dir ../server/public --public-url ./",
"build:domain": "npm run clean && npm run build"
},
The most important script is the build
script: it tells parcel to bundle all my stuff, put it in the out-dir
folder, and use the public-url
to make all file references relative to the final location where it will be running. If you do not include the latter, all file references will be hard-coded e.g. /app.123ved.css
instead of app.123ved.css
. See also the description here.
Deploying the service
Since my backend is on Node, I normally use a simple pm2
service to run it, e.g.
sudo pm2 start PATH/TO/SERVER.js --name APP_NAME
sudo pm2 ls # to see if it is running
For more information about pm2
, see here.
Other useful commands are sudo pm2 stop APP_NAME_OR_APP_ID
and sudo pm2 start APP_NAME_OR_APP_ID
.
As the server is used for many sites, the application needs to run on a dedicated port, preferably one behind a firewall, so it is not reachable from the outside. We use Nginx for that.
Configuring Nginx
Assuming you have Nginx up-and-running, add a new entry for your server in /etc/nginx/sites-available
and create a symbolic link to the /etc/nginx/sites-enabled
folder, e.g.
sudo vi bob
ln -s bob ../sites-enabled
Where the content of the file is something like the following:
upstream demoserver {
# port 55555 not reachable from Internet (firewall)
server 127.0.0.1:55555;
}
server {
location = /bob {
return 302 /bob/;
}
location /bob/ {
auth_basic "Demonstration area";
auth_basic_user_file /etc/apache2/.htpasswd;
allow 127.0.0.1;
# NOTE: The final / is important, as it will strip the prefix 'bob' from all URLs
proxy_pass http://demoserver/;
}
}
That means that our service is running on port 55555, and will be reachable via HOST_IP/bob
. Assuming, of course, that you have setup a password file. Read on...
Creating a Password File
To create username-password pairs, use a password file creation utility, for example, apache2-utils
or httpd-tools
.
Create a password file and a first user. Run the htpasswd utility with the -c
flag (to create a new file), the file pathname as the first argument, and the username as the second argument:
$ sudo htpasswd -c /etc/apache2/.htpasswd user1
Press Enter and type the password for user1 at the prompts.
Create additional user-password pairs. Omit the -c
flag because the file already exists:
$ sudo htpasswd /etc/apache2/.htpasswd user2
You can confirm that the file contains paired usernames and encrypted passwords:
$ cat /etc/apache2/.htpasswd
user1:$apr1$/woC1jnP$KAh0SsVn5qeSMjTtn0E9Q0
user2:$apr1$QdR8fNLT$vbCEEzDj7LyqCMyNpSoBh/
user3:$apr1$Mr5A0e.U$0j39Hp5FfxRkneklXaMrr/
Restarting Nginx
Test your configuration first using
sudo service nginx configtest
And if that returns OK, restart Nginx using
sudo service nginx restart
Top comments (0)