Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Riccardo Odone
Riccardo Odone

Posted on • Edited on • Originally published atodone.me

     

Rewriting to Haskell–Deployment

You can keep reading here orjump to my blog to get the full experience, including the wonderful pink, blue and white palette.


This is part of a series:


Deploy with Hapistrano

Stream was born as a Rails application. For that reason, we have been usingCapistrano to deploy it. That's why for the Servant code we have decided to employHapistrano:

Hapistrano makes it easy to reliably deploy Haskell applications to a server.

Following popular libraries like Ruby's , Hapistrano does the work of building the application with dependencies into a distinct folder, and then atomically moves a symlink to the latest complete build.

This allows for atomic switchovers to new application code after the build is complete. Rollback is even simpler, since Hapistrano can just point the current symlink to the previous release.

This is how we are currently using Hapistrano to deploy the code:

hap deploy# orHAPISTRANO_REVISION=origin/feature_branch hap deploy
Enter fullscreen modeExit fullscreen mode

What follows is ourhap.yaml:

deploy_path:'/home/stream/application-hs'host:stream@stream.example.comssh_args:-"-A"# SSH agent forwardingrepo:'git@github.com:LunarLogic/stream.git'revision:"_env:HAPISTRANO_REVISION:origin/master"build_script:-cd haskell && stack setup-cd haskell && stack build-cd haskell && stack install --local-bin-path .restart_command:sudo systemctl restart stream-hs
Enter fullscreen modeExit fullscreen mode

Server

First of all, we need to have Stack installed. This is needed because, with the above configuration, Hapistrano will build the app on the server on each deploy.

sudowget-qO- https://get.haskellstack.org | sh
Enter fullscreen modeExit fullscreen mode

Secondly, we decided that, for the time being, we will be serving the Servant code under/servant. Also, our Servant app will be running on port 8080. So let's have Nginx do the right thing:

location /servant{  proxy_pass http://127.0.0.1:8080;}
Enter fullscreen modeExit fullscreen mode

Thirdly, we want Systemd to manage the Servant process. What follows is the unit configuration we are using:

[Unit]Description=Servant AppAfter=nginx.serviceAfter=syslog.targetAfter=network.target[Service]Type=simpleRestart=alwaysExecStart=/home/stream/application-hs/current/haskell/haskell-exe#                      ^ `deploy_path` for Hapistrano.#                                     ^ `current` is where Hapistrano keeps the latest deployed app.#                                             ^ We keep the Servant code in the repo in the `haskell/` folder.#                                                     ^ Name of the executable.WorkingDirectory=/home/stream/application-hs/current/haskellStandardOutput=syslogStandardError=syslogSyslogIdentifier=servantUser=stream[Install]WantedBy=multi-user.target
Enter fullscreen modeExit fullscreen mode

Notice thathaskell-exe lives inside thecurrent release (i.e. latest) because we configure Hapistrano tostack install --local-bin-path . .

Lastly, we need to allow the stream user to restart the application by adding them to/etc/sudoers:

streamALL=(ALL) NOPASSWD: /bin/systemctl restart stream-hs
Enter fullscreen modeExit fullscreen mode

We automated all of the steps with Ansible.

We invoke it with:

- role: haskell  haskell__app_name: stream  haskell__username: stream
Enter fullscreen modeExit fullscreen mode

And here's the role:

- name: Install Stack  shell:"sudo wget -qO- https://get.haskellstack.org | sh"  args:    creates:"/usr/local/bin/stack"- name: Configure Nginx  copy:    src:"{{ item }}"    dest:"/etc/nginx/snippets/{{ haskell__app_name }}/{{ item }}"  with_items:    - haskell.conf  notify: reload nginx- name: Create haskell serviceinSystemd  template:    src: haskell.service.j2    dest: /etc/systemd/system/{{ haskell__app_name}}-hs.service    mode: 0644- name: Enable haskell serviceinSystemd  systemd:    name:"{{ haskell__app_name }}-hs"    enabled:yesdaemon_reload:yesstate: started- name: Allow user to restart the application  lineinfile:    dest: /etc/sudoers    state: present    line:"{{ haskell__username }} ALL=(ALL) NOPASSWD: /bin/systemctl restart {{ haskell__app_name }}-hs"
Enter fullscreen modeExit fullscreen mode

Get the latest content via email from me personally. Reply with your thoughts. Let's learn from each other. Subscribe to myPinkLetter!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Location
    Kraków
  • Work
    Software Maverick
  • Joined

More fromRiccardo Odone

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp