running site off development url using web.py and nginx - url

I'm developing a web site with web.py and nginx which, up until now I have been working on locally with the built in development server. Its now its time to move the site over to a live server. I'd like to deploy the site so the root is something like examples.com/test but all my url handling stuff is broken. I had thought I could create a url_prefix variable and pepper it around the web.py code but that sure seems dirty. It seems like the best thing to do would be to have nginx strip the prefix from the url so the web.py application never sees it but I'm not sure its even possible.
Does anybody know how to handle this situation?

Run the web.py app on a local port using a web server such as gunicorn, then configure nginx to host static files and reverse proxy the gunicorn server. Here are some configuration snippets, assuming that:
your project is in /var/www/example-webpy
your static files are in example-webpy/static
your nginx configuration is in /etc/nginx.
Expose the WSGI object in your application
It looks like web.py doesn't do this by default, so you'll want something like the following in your app.py (or whichever file bootstraps your app):
# For serving using any wsgi server
wsgi_app = web.application(urls, globals()).wsgifunc()
More information in this SO question.
Run your application server
Install gunicorn and start your application by running something like this (where example is the name of your Python module):
gunicorn example:wsgi_app -b localhost:3001
(You'll probably want to automate this using something like Supervisor so that the application server is restarted if your server bounces.)
Configure nginx
Put the following in /etc/nginx/reverse-proxy.conf (see this SO answer)
# Serve / from local http server.
# Just add the following to individual vhost configs:
# proxy_pass http://localhost:3001/;
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
Then configure your domain in /etc/nginx/sites-enabled/example.com.conf:
server {
server_name example.com
location /test/ {
include /etc/nginx/reverse-proxy.conf;
rewrite /test/(.*) /$1 break;
proxy_pass http://localhost:3001/;
}
location / {
root /var/www/example-webpy/static/;
}
}
Note the rewrite, which should ensure that your web.py app never sees the /test/ URL prefix. See the nginx documentation on proxy_pass and HttpRewriteModule.
This will result in requests for example.com/js/main.js to map to example-weby/static/js/main.js, so it assumes that your web.py templates didn't add a /static/ prefix. It also results in everything in the static directory becoming visible to the web, so make sure that's what you intend!

Related

How to config Rails as subdirectory of Wordpress

I'm like to config my apache server to run Wordpress on the main page and my Rails app on subdirectory. I mean:
mysite.com -> go to Wordpress
mysite.com/app -> go to Rails
How can I accomplish this?
<VirtualHost>
ServerName mysite.com
ProxyPass / https://localhost:8000/
ProxyPassReverse / https://localhost:8000/
ProxyPass /app http://localhost:3000/
ProxyPassReverse /app http://localhost:3000/
</VirtualHost>
From Apache:
In addition to being a "basic" web server, and providing static and dynamic content to end-users, Apache httpd (as well as most other web servers) can also act as a reverse proxy server, also-known-as a "gateway" server.
In such scenarios, httpd itself does not generate or host the data,
but rather the content is obtained by one or several backend servers,
which normally have no direct connection to the external network. As
httpd receives a request from a client, the request itself is proxied
to one of these backend servers, which then handles the request,
generates the content and then sends this content back to httpd, which
then generates the actual HTTP response back to the client.
So your backend will be running two separate servers: Wordpress and Rails. We just essentially change the relevant port and pass the request through. Then the content is returned to Apache and Apache generates the correct HTTP response.
Read this article for explain. click here
Two things are needed
change in application.rb file
module YourAPPName
class Application < Rails::Application
config.relative_url_root = '/runthisinrubyonrails'
# some other configuration code
end
end
change nginx configuration
upstream unicorn_sock {
server your_sock_path;
}
server {
root <path_to_your_rails_app>/public;
location #proxy_rails_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn_sock;
}
location /runthisinrubyonrails/ {
alias <path_to_your_rails_app>/public/;
try_files $uri #proxy_rails_app;
}
try_files $uri #proxy_rails_app;
some other configuration code
}

Go server with nginx reverse proxy

I've been trying to set up a go web application with docker and nginx as a reverse proxy.
My plan is to use a single domain for multiple applications e.g.: mydomain.com/myapp1.
However whenever I try to access my app in with an url like localhost/myapp/something, the request is redirected to http://localhost/something.
I've gone through all kinds of nginx configs, none of them worked, so I suspect that the problem is on the go side.
In the app itself, I'm using gorilla mux for routing, and also negroni for some middleware.
The relevant code looks something like this:
baseRouter := mux.NewRouter()
baseRouter.HandleFunc("/something", routes.SomeHandler).Methods("GET")
baseRouter.HandleFunc("/", routes.IndexHandler).Methods("GET")
commonMiddleware := negroni.New(
negroni.HandlerFunc(middleware.Debug),
)
commonMiddleware.UseHandler(baseRouter)
log.Fatal(http.ListenAndServe(":5600", commonMiddleware))
According to this, every request should go through my debug middleware, which just prints some request info to stdout, however when the redirects happen, it doesn't work.
But if the path doesn't match any handlers, everything works just fine, the standard go 404 message appears as expected, and the request is printed by the debug middleware as well.
My GET handlers generally only do something like this:
templ, _ := template.ParseFiles("public/something.html")
templ.Execute(w, utils.SomeTemplate{
Title: "something",
})
And finally, the relevant part in my nginx config:
server {
listen 80;
server_name localhost;
location /myapp/ {
# address "myapp" is set by docker-compose
proxy_pass http://myapp:5600/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
}
This kind of nginx config used to be enough for nodeJS apps in the past, so I don't understand why it wouldn't work. If anyone could point out what the hell I'm doing wrongly, I would appreciate it a lot.
Your nginx looks fine to me.
In your Go code, when you create your router, you may use the myapp as the PathPrefix like below:
baseRouter := mux.NewRouter()
subRouter := baseRouter.PathPrefix("/myapp").Subrouter()
subRouter.HandleFunc("/something", routes.SomeHandler).Methods("GET")
Or simply add myapp to the path: baseRouter.HandleFunc("/myapp/something", routes.SomeHandler).Methods("GET")
Your nginx configuration is perfectly fine.
The path you mentioned (/myapp/something) will show you 404 because you have not registered that in your routes.
I would suggest that if you wish to host multiple applications using the same domain, prefer using subdomains (myapp1.mydomain.com) instead of path (mydomain.com/myapp1).
For each subdomain, you can create a separate nginx server block by changing the server_name value only and keeping the rest of the nginx server file the same.
Then, while using middleware, you may filter out the domains and provide the requested resource.

Add URL Prefix to requests using nginx or rails

I'm trying to understand the best way to redirect all traffic for https://app.company.com/ to https://app.company.com/app
app.company.com is a rails 4.2 server which uses nginx to serve static assets and unicorn to handle the rails requests.
Should this redirect happen in nginx or rails?
Back story:
A few years ago I supported some rails apps that were installed on the intranet using URL Prefixing, like:
https://company.com/app1/
https://company.com/app2/
https://company.com/app3/
company.com ran an nginx server which routed traffic to each app server based on the url prefix.
Each app server runs nginx to serve static assets and unicorn as the rails server.
Recently a decision was made to hand management of the company.com server over to the parent company. As a result, a decision was made to route to each rails server by DNS using subdomains in place of nginx rules.
For now apps will be accessed using:
https://app1.company.com/app1/
https://app2.company.com/app2/
https://app3.company.com/app3/
Individual app servers are largely unchanged. They still run nginx and unicorn.
My main issue is understanding the best way to push traffic for the root to the url prefix
https://app1.company.com/ --> https://app1.company.com/app1/
The root route without the url prefix never reached the rails servers before.
UPDATE
Here is my nginx config file with original enhancement proposed by Vashed's answer.
I'm now curious if there is a refinement to this which would allow my config file to be independent of the server name like it was before.
upstream unicorn {
server unix:/tmp/unicorn.app1.sock fail_timeout=0;
}
server {
listen 80 deferred;
# ADDED THIS LOCATION BLOCK PER VASFED'S ANSWER
location = / {
rewrite ^ https://app1.company.com/app1;
}
location /app1/assets {
alias /var/www/application/current/public/app1/assets;
}
# Serve file uploads from nginx
location /app1/system {
alias /var/www/application/current/public/app1/system;
}
try_files $uri $uri/ #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
client_max_body_size 1G;
keepalive_timeout 10;
}
You can issue a redirect using nginx:
server{
server_name app1.company.com;
listen 443 ssl;
# other setup
location = / {
rewrite ^ https://app1.company.com/app1/;
}
location / {
# as before
}
}

Nginx with 1 domain, 2 apps. Ror + nodejs

Hey.
After a few hours of research I couldn't find any easy how-to solutions for my problem.
I have written earlier a RoR app that's deployed on my server and running just fine. Now I'm trying to deploy also a Nodejs app to run alongside my RoR app. The two apps don't have anything to do with each other - they are to be used separately.
I only have one domain to use and I'm trying to use Nginx.
The RoR app is running on Unicorn + Nginx already.
My first question is what is the correct way to deploy two separate apps alongside on the same server?
Should they listen to different ports? Other to port :80 and other to :81 for example?
Or should I alternatively use sub folders? Going for exampleDomain/app1 and exampleDomain/app2?
I also read about an option of creating sub domains, but does this work when running my apps in production?
My RoR app is deployed following these instructions:
https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-unicorn-and-nginx-on-ubuntu-14-04
(as a note I'm using Digital Ocean's virtual server)
Currently my Nginx file looks the following:
upstream app {
# Path to Unicorn SOCK file, as defined previously
server unix:/home/deploy/appname/shared/sockets/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/appname/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
It's a direct copy from the above RoR tutorial. For some reason if I switch the file name it stops working? Even that I couldn't find the file name being defined anywhere.
The file is under /etc/nginx/sites-available/ and named "default".
I tried to follow this tutorial for deploying the Nodejs app:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04
I get my app running with pm2. And I tried writing the following code in another file in /etc/nginx/sites-available/ and also including the code in the existing default file alongside with the code for RoR but neither of them worked.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://APP_PRIVATE_IP_ADDRESS:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Nginx logs are not showing anything useful either. I ran
sudo tail -f /var/log/nginx/error.log
a couple of times but the logs were empty.
I would be really thankful if someone could give me some guidance which way to go from here.
First question "How to put two apps on same server?".
All those approaches you mentioned will work, but probably the cleanest way for you and potential users would be to use a subdomain. To do this,
1) Decide on your subdomain (ie. nodejs.example.com and ror.example.com) and point both of those to your server.
2) In your 2 ngnix files for each name set the server name to the respective subdomain:
server {
listen 80;
server_name ror.example.com;
# Rest of conf below (pointing to ROR project)
}
And:
server {
listen 80;
server_name nodejs.example.com
# Rest of conf below (pointing to nodejs project)
}
Second Question: "Where do I place these files?"
To see where these files are actually used by nginx, I'd first look at the main nginx.conf file usually in the location: '/etc/nginx/nginx.conf'. There should be 2 lines near the end that tell you where nginx is looking for conf files:
http {
# A bunch of default nginx settings
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
If this is what is in your nginx.conf file, then nginx never will look in the sites-available folder. Where nginx is actually looking is in the two folders: /etc/nginx/conf.d/ and /etc/nginx/sites-enabled What I would suggest is do 3 things:
1) cd into /etc/nginx/sites-enabled folder. Remove the 'default' file.
2) create 2 files, nodejs and ror, and put the resptive nginx configurations into both of those files within the folder: /etc/nginx/sites-enabled.
3) Run:
sudo service nginx reload
sudo service nginx restart
If reload fails, run the following to help debug the configuration:
sudo nginx -t
This will show the file and line number of the issue.
Hope this helps. Comment if you have trouble with any of this.

Set public directory outside rails app

Is it possible to make public directory outside of main Rails App directory?
Schema
/apps/app1
/apps/app2
/apps/this_dir_wants_to_be_public
I need use it with several Rails and Non-Rails Applications to manage Uploads
Two ways I can think of:
First: if you are using nginx, you can configure it to first check your custom dir, and serve files from there if found, otherwise ask rails app for responce. Nginx config would look like this
upstream backend {
server localhost:3000;
}
server {
listen 80;
server_name whatever.com;
root /your_static_path;
try_files $uri $uri/index.html #backend;
location #backend {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend;
}
}
It is using nginx as a reverse proxy. You run thin server on 3000 port (or any other server you like), and nginx turns to it only if it could not find requested file in root directory.
Second: Just create symlinks
ln -s /apps/this_dir_wants_to_be_public /apps/rails_app/public
so /apps/this_dir_wants_to_be_public would be actual directory, and /apps/rails_app/public link to it. Seems absolutelly transparent for rails app and simple
Multiple public folders, single rails installation
use public.path
Symlinks may be the best approach in your case I think

Resources