I’ve written a server using Cowboy. The server responds fine when running on my desktop. I can connect to it from my phone and receive expected data. But, after I moved it to a VM in the Google Cloud it is unreachable. The VM has an static IP that I know works, because I get the default Apache Server page when navigating to the static IP in a browser. Also when I shut down the Apache server, I get a 404 as expected. Here’s what I tried so far.
1.
I’ve tried modifying my sys.config file to specify an IP address but that prevents the server from starting at all. In short, is there a way to make Cowboy based server listen to connections on a specific IP address?
Not to be “that guy”, but … if the IP and everything is correct then unless there’s some reverse proxy or something going on, when you shut down Apache you shouldn’t get a 404, just a browser connection failure (or possibly a timeout depending on firewall stuff). Is that what you mean by unreachable? If so then when you’re running the cowboy server, try doing curl 0.0.0.0:8080 from a shell on the VM to make sure it’s connecting, to rule out any internal networking stuff, and also curl ipinfo.io to check the public IP your VM is listening on. Also presumably the default Apache is on port 80 but you’re running cowboy on 8080 - is port 8080 open in the GCP firewall?
Igor, the two commands you gave me, curl 0.0.0.0:8080 and curl ipinfo.io helped me track down the problem. First, 8080 was closed (although the Google cloud console said it was opened), secondly the static IP address I have from Google is visible to the outside world and port 80 is accessible. Third, instead of 0.0.0.0:80 I had to use "my.ip.add.ress:80 Last but not least, I had to start the Cowboy server using sudo, otherwise the server was restricted from using any ports at all. I can now connect to the server, send and receive data. I have been a client-side programmer (C/C++/Kotlin) most of my career. Server-side programming in Erlang is like learning how to walk again. I greatly appreciate your help. Thank you, Igor.
In addition to what everyone else has said, if you need to run Apache sites as well, then you can use HAProxy to forward traffic to the correct ports. Here’s an example:
global
#
# upload to: /etc/haproxy/
#
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
# log 127.0.0.1 local2
tune.ssl.default-dh-param 2048
ssl-default-bind-options no-sslv3 no-tls-tickets
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
ssl-default-server-options no-sslv3 no-tls-tickets
ssl-default-server-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
# chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
tune.ssl.default-dh-param 2048
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
# option forwardfor except 127.0.0.0/8
option forwardfor
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend http-in
bind *:80
bind :::80
bind *:443 ssl crt /etc/haproxy/certs/ no-sslv3 no-tlsv10
bind :::443 ssl crt /etc/haproxy/certs/ no-sslv3 no-tlsv10
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
default_backend main_apache_sites
reqadd X-Forwarded-Proto:\ https if { ssl_fc }
# Define hosts
redirect prefix http://domain1.com code 301 if { hdr(host) -i www.domain1.com }
acl host_1 hdr(host) -i domain1.com
redirect prefix http://domain2.com code 301 if { hdr(host) -i www.domain2.com }
acl host_2 hdr(host) -i domain2.com
#Redirect sites to HTTPS
acl ssl_redirect_hosts hdr(Host) -i domain1.com
acl ssl_redirect_hosts hdr(Host) -i domain2.com
redirect scheme https if ssl_redirect_hosts !{ ssl_fc }
redirect scheme https code 301 if !{ ssl_fc }
# figure out which one to use
use_backend b_1 if host_1
use_backend b_2 if host_2
backend main_apache_sites
server server1 127.0.0.1:8080 cookie A check
cookie JSESSIONID prefix nocache
backend b_1
server server2 127.0.0.1:8888 cookie A check
cookie JSESSIONID prefix nocache
backend b_2
server server3 127.0.0.1:8889 cookie A check
cookie JSESSIONID prefix nocache
backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321
This is where you’d configure Apache to listen on 8080, Erlang site one to listen on 8888, Erlang site 2 on 8889, etc. The great thing about this is HAProxy takes care of https as well (you can use lets encrypt (with this guide) for certs).