The old now you see me, now you don’t website trick!
Phoenix has deployment guides but all you really need to do is build your release and then run mix phx.server with MIX_ENV=prod. Then you need a way of the internet accessing that website, which is on port 4000 by default. There are tools like ngrok that will do that for you. I think most dynamic DNS services cost money.
Aren’t your costs close to 0 (electricity) if it’s hosted on your laptop? What’s your data allowance like? It’s certainly an odd desire. There are free/cheap hosting services out there which will be safer.
You could grab a cheap Raspberry Pi or any old mini desktop/laptop lying around and install Ubuntu/Debian on it then follow the official Phoenix guides on Deployment. You can run with MIX_ENV=prod mix phx.server or build a release and run that. Then it’s a matter of inbound port forwarding on your firewall to your system or using something like ngrok (as @cmo suggested). That way your site can stay up even when you are using your laptop or traveling, etc.
It will take a little work to setup HTTPS… I would go for Nginx Proxy Manager in this case since it’s so easy to setup a reverse proxy with automatic free Let’s Encrypt. Also I would use free DuckDNS if you need dynamic DNS.
Personally I would build the Phoenix App as a Docker container (so it can be deployed anywhere), install Docker Engine/swarm on a Raspberry Pi cluster, and deploy that way. There is a learning curve with Docker but once it clicks it will greatly benefit your ability to self-host anything.
Great posts on doing that with Phoenix are on this site:
You may have security, availability, and/or bandwidth performance issues to deal with but it would work without giving money to expensive cloud providers.
However my use case was demo and active development with live feedback over a call so that I didn’t have to redeploy after each change. I never used it for serving an application ongoing.
I couldn’t imagine serving anything from a laptop is anything but a hobby level consideration or a specific local network use case.
It it’s for an ongoing use over the internet I would say its actually easier and definitely a better experience for your users to deploy to fly.io using their free hobby plan. If you find that you need a bit more than that then it can be as little as $5 per month.
I see no harm done by serving from your personal devices, especially for personal projects that only you or a select few will have access to them.
I always wondered if it is possible to buy a proxy with static ip and set some kind of reverse connection, where traffic will flow through the proxy to your local device. I have a server laying around but never got it running because my provider blocks all incoming traffic to my router.
This is the answer, ngrok is what you are looking for at a short-term level, it lets you broadcast localhost.
I think the most important question is what is your budget, you can get decent hosting for $5 (I’m from South Africa, so I know the pain of currency conversations and costs) if your budget is truly $0 either cause of lack of funds or lack of an easy way to pay.
You can use fly.io, they don’t charge for usage that is less than $5.00, you can only deploy one app, this for some reason isn’t advertised.
I’ve used the likes of https://tunnelto.dev (with a caveat to use cargo install tunnelto rather than the version from homebrew which has a bug preventing LV websocket from working) and https://tunnel.pyjam.as (which are similar to ngrok) as a way to do quick demos and integration testing without requiring a deploy.
That’s what the free CloudFlare tunnel provides. You run the tunnel on your home machine or laptop and it connects out to CloudFlare so there is not much your ISP can do about it. Then CloudFlare proxies traffic to your machine using the tunnel.
Unlike the simple and limited ngrok you can use your own domains with CloudFlare tunnel on the free tier. Also if you have multiple apps you want to serve from your machine, they can all use the same tunnel on the free tier as well. If you want multiple tunnels to multiple machines then you may need to use a paid tier.
I wouldn’t use a laptop, but I have served complex applications from a home pc. I get one $5 per month VPS, and setup a ssh reverse port forwarding tunnel from my home pc to the VPS, eg: ssh -N -R 8080:localhost:4000 username@myvps_on_internet Then I have nginx running on the vps that proxy to port 8080 for a virtual host.
This way you don’t need anything other than plain old ssh and nginx. And now you can run application that does not fit in the lame $5 VPS.
To be fair I was thinking about this before, but never was sure what happens when the connection gets interrupted, but I think that a sh script may be able to handle restarts, have you tried to run this for a longer period?
DISCLAIMER: Obviously, leaving ports opened and accessible from the Internet can be a major security vulnerability. If you’re gonna do this, make sure you are careful. (EDIT: If you don’t understand the risks involved with forwarding ports, then either learn the risks before you do it and do it safely, or use something like ngrok or tailscale to bypass the problem.)
The process isn’t too complicated in principle (as long as your ISP doesn’t block this functionality at some level or another):
Start a server
Enable port forwarding on your router
Find out your external network IP address (this part may not work for some ISPs)
Access the service from another device outside your network
An easy way to do a “Hello World” server experiment would be like this:
Start Python’s built-in HTTP server: python3 -m http.server 8080 (do this from a directory that doesn’t have sensitive files)
Configure your router so that port 8080 is being forwarded to the IP address of your computer in your LAN. (May need to look up your internal IP address)
Find your external IP address: Visit https://icanhazip.com in your browser.
Access your new server from outside your network: Visit http://126.96.36.199:8080/ in your browser (obviously replace the 123s with your external IP address).
Exit the server and disable port forwarding in your router (don’t want to leave yourself exposed like that)
Now, you can replace all these steps with Phoenix. The only big difference I can think of is to change the config/dev.exs to use 0.0.0.0 instead of 127.0.0.1. And Phoenix uses port 4000 by default, so just open that port instead.
It is a production grade service and used by many large CloudFlare customers to lock down their infrastructure. This means you can start on your own machine and grow into a cloud hosted solution seved in multiple regions and manage the transition seamlessly.
Your service is unreachable directly as DNS points to CloudFlare IP, not your IP.
You don’t open any inbound ports. It’s just an outbound flow from your machine to CloudFlare.
All traffic is encrypted between your machine and CloudFlare
The tunnel is established to the nearest CloudFlare datacenter automatically, reducing latency.
You can drop all inbound traffic ports and protocols on your router/firewall.
CloudFlare provides all of its normal protections including DDOS.
Free Web Application Firewall (WAF) for anything served over the tunnel.
Its just not worth going out of one’s way to jerry build a half baked insecure solution.
None of the other solutions presented in this thread addressed critical security requirements when serving an application on the internet. They didn’t address DDOS, bots, WAF or DNS hosting reliability.
My advice is be careful and deliberate in your choices, don’t ignore critical security requirements and don’t ignore free plans from reputable service providers.