Deploy a Play! Framework Application behind nginx -> haproxy -> netty (Play2 core) for transient upgrading. This setup fully supports Websockets in almost any variation. - But most importantly uses 2 instances minimum to allow seamless upgrade. Prepare the instances with "cd app/instances/$instance && ~/app/play/play clean compile stage"
fooapp@srv:~$ cat app/env/PLAY_OPTS | |
export DATABASE_URL="jdbc:postgresql://127.0.0.1/foobar" | |
# We could wire a different configuration file here | |
# or set up a different database on the fly | |
export PLAY_OPTS="-DapplyEvolutions.default=true -DapplyDownEvolutions.default=true -Ddb.default.url="$DATABASE_URL" -Ddb.default.user=fooapp -Ddb.default.password=fooapppw -Ddb.default.driver=org.postgresql.Driver" |
#!/bin/bash | |
# These environment variables are sometimes needed by the running daemons | |
export USER=fooapp | |
export HOME=/home/fooapp | |
# Include the user-specific profile, it's actually called .profile on debian. | |
$HOME/.profile | |
# You can load ENV-Vars from a file. | |
# I load $PLAY_OPTS from it to read database configuration | |
# and evolutions settings | |
source "$HOME/app/env/PLAY_OPTS" | |
# Now let's go! | |
# New Relic Agent is loaded as well from a known place | |
exec /home/fooapp/app/instances/alpha/target/universal/stage/bin/fooapp -J-javaagent:/home/fooapp/app/lib/newrelic/newrelic.jar -Dhttp.port=62002 "$PLAY_OPTS" 2>&1 |
# There's more! Common structure ensures easy management through some scripts in ~/app/bin, | |
# ENV-var files in ~/app/env, a git repo in ~/app/src, Play in ~/app/play, libs, configs for daemontools daemons in ~/app/etc | |
# and most importantly at least two play instances to minimize downtime. | |
fooapp@serv:~$ tree app -L 2 | |
app | |
├── bin | |
│ ├── control | |
│ └── manage | |
├── downloads | |
│ └── play-2.2.2.zip | |
├── env | |
│ └── PLAY_OPTS | |
├── etc | |
│ └── haproxy | |
├── instances | |
│ ├── alpha | |
│ └── beta | |
├── lib | |
│ └── newrelic | |
├── play | |
│ ├── CONTRIBUTING.md | |
│ ├── framework | |
│ ├── play | |
│ ├── play.bat | |
│ ├── README.md | |
│ ├── repository | |
│ └── samples | |
├── src | |
│ ├── branches | |
│ ├── config | |
│ ├── description | |
│ ├── HEAD | |
│ ├── hooks | |
│ ├── info | |
│ ├── objects | |
│ └── refs | |
└── templates | |
├── haproxy.cfg.tpl | |
└── post-receive.tpl | |
21 directories, 13 files |
# I run haproxy with DJBs daemontools, so no daemon here | |
global | |
log 127.0.0.1 local0 | |
log 127.0.0.1 local1 notice | |
#log loghost local0 info | |
maxconn 4096 | |
#debug | |
#quiet | |
user fooapp | |
group fooapp | |
defaults | |
log global | |
mode http | |
option httplog | |
option dontlognull | |
retries 3 | |
option redispatch | |
maxconn 2000 | |
contimeout 5000 | |
clitimeout 50000 | |
srvtimeout 50000 | |
listen fooapp-master 127.0.0.1:62000 | |
mode http | |
stats enable | |
# change this, or disable stats! | |
stats auth user:statspw | |
balance leastconn | |
option httpclose | |
option forwardfor | |
option httpchk GET / HTTP/1.0 | |
server alpha 127.0.0.1:62002 check | |
server beta 127.0.0.1:62003 check |
server { | |
server_name fooapp.org; | |
listen server.ip; | |
listen [ip:v6:ip] default_server ipv6only=on; | |
root /home/appuser/public_html; | |
index index.html index.htm index.php; | |
access_log /var/log/nginx/fooapp_access_log; | |
error_log /var/log/nginx/fooapp_error_log; | |
ssl_certificate /home/fooapp/ssl.cert; | |
ssl_certificate_key /home/fooapp/ssl.key; | |
# Little caveat: on upgrade of alpha (which involves the "clean" task, | |
# this would fail. See fx http://stackoverflow.com/questions/5555419/nginx-search-for-static-content-in-multiple-directories | |
# for a possible solution | |
location /assets { | |
root /home/fooapp/app/instances/alpha/target/scala-2.10/classes/public; | |
rewrite ^/assets(/.*)$ $1 break; | |
} | |
location / { | |
# haproxy balances on port 62000 | |
proxy_pass http://127.0.0.1:62000; | |
proxy_redirect off; | |
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_set_header X-Forwarded-Proto $scheme; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
proxy_buffering off; | |
proxy_connect_timeout 43200000; | |
proxy_read_timeout 43200000; | |
proxy_send_timeout 43200000; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment