App Daemon
Our server uses NGINX as Reverse Proxy for HTTP and HTTPS traffic and it is used to serve static files and proxy requests to your app.
Because it operates for all users on the server, only a limited set of features are configurable, the only way to configure it is via the deployment system. Fornatunely, we also give you a special page to make customizing it much easier.
If you never heard NGINX before, you can read some of good resorces here:
You can either edit NGINX config directly or via our interactive form.
Editing NGINX config directly
The text area contains current NGINX script and you can freely edit it. When you click Apply it will convert your changes to deployment script like this:
nginx: |
server {
....
}
Behind the scene it will convert your input to YAML script represented in our NGINX deployment script reference hence you won't be able to change certain protected values such as IP addresses, PHP proxy pass, etc.
You won't be able to edit root path via direct script. To change it, use YAML config.
nginx:
root: public_html/public
Editing the root path this way will keep the rest config untouched.
Editing NGINX config interactively
The interactive NGINX config contains easy-to-read NGINX config that covers about 80% of usage for popular frameworks. When you click Apply it will convert your input to YAML script represented in our NGINX deployment script reference. The current setup shown represents auto-detected config of your choosing.
Beware! Changing NGINX config this way may erases your customized NGINX config not represented using the form.
Option | What is it? |
---|---|
Root Path | The directory where NGINX searches for static files before being forwarded to app |
Resolve Type | What is the kind of your app? |
- Static | No app, just HTML files |
- PHP-FPM | PHP Handled by fastcgi_pass |
- Phusion App | Special handling for Node.js/Python/Ruby apps |
- Generic App | Any kind of app (Traffic forwarded via $PORT arg/envar) |
- Forward Port | Forward to hardcoded/docker/unit port via proxy_pass |
- Deny Requests | Deny all requests (useful for subfolder config) |
The PHP-FPM mode has some useful preset
Option | What is it? |
---|---|
- Smart | XAMPP-like webpages (hide .php extension) |
- Root Index - Safe | Route all extension-less pages to /index.php |
- Root Index - Standard | Route all pages to /index.php as REQUEST_URI |
- Root Index - Always | Route all pages to /index.php as PATH_INFO |
Please refer to PHP deployment setup for each of security implication.
The Static mode also has some useful preset below and a way to configure custom 404
page.
Option | What is it? |
---|---|
- Default | Nothing special |
- Smart | Allow hiding .html extension |
- Root Index | Route all pages to /index.html (Treats all as 200 OK ) |
- Auto Index | Allow listing directory and expose all file lists |
Editing NGINX Config via YAML Script
Below is the example of the configuration:
nginx:
fastcgi: 'on'
root: public_html
index: index.html index.php
ssl: 'on'
Please see NGINX deployment script reference for advanced configuration that we can offer.
Configure NGINX for HTTPS
The ssl
option has three options: always
, on
, off
. The always
option will force the server to redirect all HTTP traffic to HTTPS. The default value for ssl
is on
.
Configure NGINX for PHP
The fastcgi
option has three options: always
, on
, off
. The default value for fastcgi
is off
.
This section is covered more in the PHP Deployment section.
Configure NGINX for Generic Apps
NGINX by default only forwards connection and can't invoke the desired app to run. We use Phusion Passenger so we can tell NGINX to invoke the app and forwards HTTP requests.
The minimum configuration to enable NGINX for Generic apps is:
nginx:
root: public_html/public
passenger:
enabled: on
app_start_command: npm start
Which is equivalent to running npm start
in the public_html
(parent of root
) directory, with the PORT
environment variable set to the port that NGINX is listening to.
Passenger's enabled: on
config is required to indicate that Passenger's module is activated for given host.
It is important that root
is set to the directory that contains the public
directory. This is because NGINX will serve the public
directory as the root directory for serving static files as you don't want to expose the entire app scripts to the public.
If the app must be called from a subdirectory, you can use the app_root
option to specify the directory that contains the app. For example, if the main app file is in public_html/server/app.js
, you can set the app_root
to public_html/server
:
nginx:
root: public_html/public
passenger:
enabled: on
app_root: public_html/server
app_start_command: node app.js
PORT environment variable
The PORT
environment variable is set by Phusion Passenger. It is a random port that's chosen as a HTTP proxy between your app and the internet.
Your app must listen to PORT
to be able receiving HTTP requests from NGINX.
You can tell the app to listen to this port with another envar name using env
like this:
nginx:
passenger:
app_start_command: env HTTP_PORT=$PORT node app.js
Or you can set the port using the app's argument if available:
nginx:
passenger:
app_start_command: node app.js --port $PORT
If you have designed your app to listen to PORT
envar, leave it all alone:
nginx:
passenger:
app_start_command: node app.js
All examples here assume your app listen to 127.0.0.1
, not localhost
or ::1
.
For example in rust, you might have to specify it like env TARGET=127.0.0.1:$PORT cargo run
.
If you make a social media app bot, you'll realize that the only way to make it work is via a webhook. It's a limitation by design, as we're not allowing any software running 24/7 and running a background polling.
Set Environment Variables
Passenger has three ways to set environment variables:
app_env
option
The app_env
option is special option that's used to set environment mode. The default value is production
. This option sets the value to the following environment variables:
RAILS_ENV
RACK_ENV
WSGI_ENV
NODE_ENV
PASSENGER_APP_ENV
You can set this value other values such as development
or test
.
env_var_list
option
The env_var_list
option is used to set environment variables directly from NGINX. It's a list of environment variables to set. The value is a string that's in the format of KEY=VALUE
. For example:
nginx:
passenger:
enabled: on
app_start_command: node app.js
env_var_list:
- APP_SECRET=SECRET_VALUE
- APP_CONFIG={"key":"value"}
~/.bashrc
file
Passenger reads the ~/.bashrc
file to set environment variables. You can set environment variables in this way. For example run this command to edit the ~/.bashrc
file via SSH:
nano ~/.bashrc
Then add the following line to the file:
export APP_SECRET=SECRET_VALUE
The environment variable will be set when the app is started next time.
More information about setting environment variables can be found in the Passenger documentation.
Restarting App
Any edits either in the app file or ~/.bashrc
file will not be applied until the app is restarted. You can restart the app forcibly by running restart
in SSH, which will actually calls:
killall -u $USER
The alternative way to restart app can be found in the Passenger documentation. Global NGINX Reload will also restart your app unless you're using Proxfix NOHUP.
For some connection using Node CJS, Python WSGI or Ruby config.ru, you may need to restart by passenger-config restart-app ~
. We have some reports restarting don't work with restart
alone.
Websocket
Websocket should works out of the box since only one app is spawned per website configuration. However, The websocket disconnects if NGINX reloads. To retain websocket data after NGINX reload, use Proxfix NOHUP
Proxfix NOHUP
proxfix
NOHUP mode is a custom made proxy app designed to overcome Phusion limits during NGINX restarts. To setup proxfix
NOHUP mode, prefix your app start command with proxfix
with NOHUP=1
envar like below:
nginx:
passenger:
enabled: on
app_start_command: proxfix node app.js
env_var_list:
- NOHUP=1
proxfix
will call node app.js
outside from NGINX tree. So, when NGINX restarts, your app will not killed, it retains it's memory. NGINX simply calls proxfix
who then proxies NGINX requests to your already-running app.
This has a downside that when you change proxfix parameters, it will not be restarted. you must call restart
to really restart it.
X-Forwarded-For
and X-Forwarded-Proto
Passenger will always add X-Forwarded-For
and X-Forwarded-Proto
to give the app client IP addresses and HTTP scheme.
To determine client IP address or HTTP scheme reliably, you have to know how many layers of proxy needed to reach your site.
For example, this is the example of response headers from user IP 123.45.67.89
when there's no proxy via HTTPS.
x-forwarded-for: 123.45.67.89
x-forwarded-proto: https
If the user is same but you're under a webproxy such as CloudFlare (assume IP 32:231::1), then it would be like this
x-forwarded-for: 123.45.67.89, 32:231::1
x-forwarded-proto: https, http
The X-Forwarded-Proto
is equally important to determine whether you should send a secure or plain cookies. This mean your app must be configured to trust proxy headers. Some framework may already do it, some other need be set explicitly.
Language-Specific Configuration
More information about configuring NGINX for specific languages can be found in the Deployment section.
Advanced Configuration
All other available options are specified in Deployment System section.
Global Configuration
Global configuration of NGINX cannot be changed. However, some of the configuration are set as optimally as possible. You can see more about the global configuration in this file. Some of the interesting configuration are:
- Static files are cached with
7d
expiration time. - Gzip are enabled for
css
,js
,svg
static files. - Maximum file upload size is set to 512MB.
- There's rate limit of 2 requests per second with 500 burst request per IP address to mitigate DoS attack.
- TLSv1.2 is the minimum HTTPS version to support, which works for browsers as old as Windows 7 era (with IE 11), older browsers such as in Windows XP era will not be able to open your website.