AnyCable
This guide shows you how to replace Action Cable with AnyCable. Both provide similar functionality, but have different scaling characteristics. While AnyCable has the potential to reduce RAM requirements on large deployments, the need to run multiple processes makes it impossible to run AnyCable alongside even a tiny Rails application on a 256MB machine. A minimum of 512MB is required.
The configuration below also runs nginx as a reverse proxy to avoid any firewall issues.
It also runs everything on one VM, which has a number of downsides including dropping socket connections every time a new version of your application is deployed. For another take on configuring AnyCable to run on fly.io, see Fly.io Deployment on the anycable site.
Prepare your application
If you haven’t already dones so, perform the steps described in the
Provisioning Redis section of the Getting Started guide. Also be sure that the pg
gem is listed
in your Gemfile
.
Now add the anycable-rails
gem:
bundle add anycable-rails
Edit config/cable.yml
thus:
production:
- adapter: redis
- url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
- channel_prefix: namelist_production
+ adapter: any_cable
Update your image
Modify Dockerfile
to install foreman
, anycable-go
and nginx
:
FROM base
+RUN gem install foreman
+RUN curl -L https://go.dev/dl/go1.19.linux-amd64.tar.gz | tar xz -C /opt
+RUN GOBIN=/usr/local/bin /opt/go/bin/go install github.com/anycable/anycable-go/cmd/anycable-go@latest
+
-ARG PROD_PACKAGES="postgresql-client file vim curl gzip libsqlite3-0"
+ARG PROD_PACKAGES="postgresql-client file vim curl gzip libsqlite3-0 nginx"
ENV PROD_PACKAGES=${PROD_PACKAGES}
RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
--mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \
apt-get update -qq && \
apt-get install --no-install-recommends -y \
${PROD_PACKAGES} \
&& rm -rf /var/lib/apt/lists /var/cache/apt/archives
+
+ADD config/nginx.conf /etc/nginx/sites-available/default
COPY --from=gems /app /app
COPY --from=node_modules /app/node_modules /app/node_modules
Edit fly.toml
to run foreman::
[env]
PORT = "8080"
- SERVER_COMMAND = "bin/rails fly:server"
+ SERVER_COMMAND = "foreman start -f Procfile.fly"
Add Procfile.fly
to start the four processes required:
nginx: nginx -g 'daemon off;'
server: bin/rails server -p 8081
anycable: bundle exec anycable
ws: anycable-go --port=8082
Add config/nginx.conf
to reverse proxy cable traffic to anycable-go and send the
remainder to your Rails application::
server {
listen 8080 default_server;
listen [::]:8080 default_server;
location /cable {
proxy_pass http://localhost:8082/cable;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
location / {
proxy_pass http://localhost:8081/;
proxy_set_header origin 'https://localhost:8081';
}
}
Deployment
If you haven’t already done so, scale your machine:
fly scale vm shared-cpu-1x --vm-memory 512
Now you are ready to deploy:
fly deploy