<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: João Ferreira</title>
    <description>The latest articles on DEV Community by João Ferreira (@jmnsf).</description>
    <link>https://dev.to/jmnsf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F451892%2F54d85d09-7bf0-46f9-8a3d-df279606d7b9.jpeg</url>
      <title>DEV Community: João Ferreira</title>
      <link>https://dev.to/jmnsf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jmnsf"/>
    <language>en</language>
    <item>
      <title>Pagekite: expose your team's localhosts to the world under your own domain</title>
      <dc:creator>João Ferreira</dc:creator>
      <pubDate>Thu, 13 Aug 2020 14:11:39 +0000</pubDate>
      <link>https://dev.to/jmnsf/pagekite-expose-your-team-s-localhosts-to-the-world-under-your-own-domain-169a</link>
      <guid>https://dev.to/jmnsf/pagekite-expose-your-team-s-localhosts-to-the-world-under-your-own-domain-169a</guid>
      <description>&lt;p&gt;I've been using &lt;a href="https://ngrok.com/"&gt;ngrok&lt;/a&gt; for years to expose my dev servers to the world, usually so I can receive webhooks or test OAuth flows. It works amazingly well, and the price is reasonable.&lt;/p&gt;

&lt;p&gt;It was a lifesaver as a sole dev building &lt;a href="https://skoach.com"&gt;Skoach&lt;/a&gt; because, by nature of the app being a chatbot, every local server needs to receive webhooks from Slack and other channels. As the team grows and more people touch code, it translates to an additional ngrok account at ~$8/mo per dev. But startups are supposed to be frugal, right?&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://pagekite.net/"&gt;Pagekite&lt;/a&gt;. It's got more features than ngrok with an arguably more complex interface, but it's open source and we can host our own "frontend" (i.e.: the public server that tunnels our requests). I figured I'd set this up once on a cheap server somewhere, and have a bunch of tunnels available for everyone on the team, with the bonus of using our own domain. Plus, I wrote it all down for posterity 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  In this article we'll explore how to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Generate a wildcard certificate for a domain using LetsEncrypt (you can skip this section if you don't need Pagekite to handle encryption for your https tunnels)&lt;/li&gt;
&lt;li&gt;Set up a Pagekite "frontend" on a publicly facing linux server with https support&lt;/li&gt;
&lt;li&gt;Configure a Pagekite "backend" (the client your run locally) to use our server for tunneling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A public linux server somewhere, hopefully geographically near your team for lower latencies. A $5 DigitalOcean droplet will do (cheaper than ngrok even!), but EC2, Azure, or equivalent will work. My choice of distro was ubuntu in this particular case.&lt;/li&gt;
&lt;li&gt;Your own domain, and DNS access to it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Generate wildcard certificate
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ssh&lt;/code&gt; into your server and make sure certbot is installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And build your certificate + key for the domain you selected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot certonly &lt;span class="nt"&gt;--manual&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--preferred-challenges&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dns &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--email&lt;/span&gt; YOUR_EMAIL &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--server&lt;/span&gt; https://acme-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--agree-tos&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--manual-public-ip-logging-ok&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"*.dev.skoach.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You should pick a domain under which all your tunnels will be created. For example, &lt;code&gt;*.dev.skoach.com&lt;/code&gt; would let us create &lt;code&gt;alice.dev.skoach.com&lt;/code&gt;, &lt;code&gt;bob.dev.skoach.com&lt;/code&gt; and so on. We'll use this as an example going forward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This command will start the certificate creation &amp;amp; domain validation flow. It'll ask you to add a DNS record to your domain, the scope of which is beyond this article. There are &lt;a href="https://certbot.eff.org/docs/using.html#getting-certificates-and-choosing-plugins"&gt;other ways&lt;/a&gt; to verify your domain as well.&lt;/p&gt;

&lt;p&gt;You should end up with 4 files under &lt;code&gt;/etc/letsencrypt/live/dev.skoach.com&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;total 12
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 root root  692 Aug 12 18:36 README
lrwxrwxrwx 1 root root   43 Aug 12 18:36 cert.pem -&amp;gt; ../../archive/dev.skoach.com/cert1.pem
lrwxrwxrwx 1 root root   44 Aug 12 18:36 chain.pem -&amp;gt; ../../archive/dev.skoach.com/chain1.pem
lrwxrwxrwx 1 root root   48 Aug 12 18:36 fullchain.pem -&amp;gt; ../../archive/dev.skoach.com/fullchain1.pem
lrwxrwxrwx 1 root root   46 Aug 12 18:36 privkey.pem -&amp;gt; ../../archive/dev.skoach.com/privkey1.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Generate a cert + key file for Pagekite
&lt;/h3&gt;

&lt;p&gt;An additional step is required here because Pagekite expects the certificate and its private key to be in the same file, but LetsEncrypt generates them separately. This is easy enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cat&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /etc/letsencrypt/live/dev.skoach.com/fullchain.pem &lt;span class="se"&gt;\&lt;/span&gt;
    /etc/letsencrypt/live/dev.skoach.com/privkey.pem &lt;span class="se"&gt;\&lt;/span&gt;
    | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/letsencrypt/live/dev.skoach.com/keycert.pem &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Just &lt;strong&gt;remember to run this&lt;/strong&gt; after every time you renew your certificates. Take special care if you're auto-renewing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up your DNS
&lt;/h3&gt;

&lt;p&gt;In case you haven't already, you'll have to point your wildcard domain to your Pagekite server. The details can vary a bit with your DNS &amp;amp; server hosts and is beyond the scope of this article, but as an example, with CloudFlare DNS and a DigitalOcean droplet you'd have to add an A record with &lt;code&gt;*.dev&lt;/code&gt; as the hostname pointing to your droplet's IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up Pagekite
&lt;/h2&gt;

&lt;p&gt;We've got our certs, so lets get Pagekite going. Download all the things:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;dirmngr
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;deb http://pagekite.net/pk/deb/ pagekite main | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/apt/sources.list
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key adv &lt;span class="nt"&gt;--recv-keys&lt;/span&gt; &lt;span class="nt"&gt;--keyserver&lt;/span&gt; keys.gnupg.net AED248B1C7B2CAC3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;pagekite
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;See &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-pagekite-front-end-server-on-debian-9#step-2-%E2%80%94-installing-pagekite-on-the-front-end-server"&gt;this guide&lt;/a&gt; if you're curious about what each of these commands do.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pagekite includes several config files and some defaults for being used as a backend server. This isn't what we want, so lets go into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/pagekite.d/10_account.rc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And comment out everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#################################[ This file is placed in the Public Domain. ]#
# Replace the following with your account details.

# kitename   = NAME.pagekite.me
# kitesecret = YOURSECRET

# Delete this line!
# abort_not_configured
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then configure the frontend in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/pagekite.d/20_frontends.rc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Comment out the &lt;code&gt;defaults&lt;/code&gt; line, and add the following (make sure to change the domains):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;isfrontend
&lt;span class="nv"&gt;ports&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80,443
&lt;span class="nv"&gt;protos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http,https
&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http,https:&lt;span class="k"&gt;*&lt;/span&gt;.dev.skoach.com:ASECRETFORYOURKITES

&lt;span class="c"&gt;# Skip the next line if you don't need HTTPS encryption handled by Pagekite&lt;/span&gt;
&lt;span class="nv"&gt;tls_endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.dev.skoach.com:/etc/letsencrypt/live/dev.skoach.com/keycert.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You'll use &lt;code&gt;ASECRETFORYOURKITES&lt;/code&gt; to authenticate your backends later. Now, restart Pagekite to effect these changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart pagekite.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And set it up to start on boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;pagekite.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your server's behind a firewall (as it should be) remember to open ports 80 and 443. With ufw this would be &lt;code&gt;sudo ufw allow 80&lt;/code&gt; and &lt;code&gt;sudo ufw allow 443&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Configure your Pagekite backend
&lt;/h2&gt;

&lt;p&gt;All we need to do now is set up our local Pagekite to connect to our new frontend. You can download it &lt;a href="https://pagekite.net/downloads"&gt;here&lt;/a&gt; if you haven't yet. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Although it says Python 2.7 is required, &lt;a href="https://github.com/pagekite/PyPagekite/issues/40#issuecomment-558745913"&gt;the team has made all required changes&lt;/a&gt; for it to work on Python 3 (and I've used it as such). If you have issues running the script directly, try running it with &lt;code&gt;$ python3 pagekite.py&lt;/code&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Run it once so it'll create default configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pagekite something-unique.pagekite.me
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will create the config file that you'll edit next. It should be &lt;code&gt;~/.pagekite.rc&lt;/code&gt; under MacOS and linux, or &lt;code&gt;C:\Users\your-username\pagekite.cfg&lt;/code&gt; under Windows. Add the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# kitename is the URL for your tunnel. Should be *something*.YOUR.DOMAIN.TLD,&lt;/span&gt;
&lt;span class="c"&gt;# and unique among your tunnels/devs&lt;/span&gt;
kitename   &lt;span class="o"&gt;=&lt;/span&gt; jf.dev.skoach.com
&lt;span class="c"&gt;# kitesecret should match what you picked for your frontend under the "domain" config&lt;/span&gt;
kitesecret &lt;span class="o"&gt;=&lt;/span&gt; ASECRETFORYOURKITES

&lt;span class="c"&gt;# URL for your frontend&lt;/span&gt;
frontend &lt;span class="o"&gt;=&lt;/span&gt; dev.skoach.com:80

&lt;span class="c"&gt;# Your tunnel. This will expose whatever's on port 8000 to the public URL picked above &lt;/span&gt;
service_on &lt;span class="o"&gt;=&lt;/span&gt; http:@kitename:localhost:8000:@kitesecret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Save and run pagekite again. It should connect to your frontend and expose your local port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pagekite
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; Hello! This is pagekite.py v1.5.2.200725.                   &lt;span class="o"&gt;[&lt;/span&gt;CTRL+C &lt;span class="o"&gt;=&lt;/span&gt; Stop]
    Connecting to front-end relay 134.209.88.195:80 ...
     - Relay supports 2 protocols on 2 public ports.
     - To &lt;span class="nb"&gt;enable &lt;/span&gt;more logging, add option: &lt;span class="nt"&gt;--logfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/logfile
~&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Flying localhost:8000 as https://jf.dev.skoach.com/
 &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;pagekite&lt;/span&gt;&lt;span class="sh"&gt;.py [flying]   Kites are flying and all is well.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You're all set! Just repeat this chapter for each tunnel &amp;amp; dev that you want to set up and you're done 💪.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;Thanks to whoever wrote &lt;a href="https://kirelos.com/expose-localhost-to-internet-with-pagekite-on-ubuntu/"&gt;this tutorial&lt;/a&gt;, Renato Candido for &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-pagekite-front-end-server-on-debian-9"&gt;this guide&lt;/a&gt;, and to the Pagekite team for building awesome software 👌.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://www.linkedin.com/in/norberto-vasconcelos/"&gt;Norberto&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/vanessaes/"&gt;Vanessa&lt;/a&gt; for reviewing this article.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://unsplash.com/@allecgomes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Allec Gomes&lt;/a&gt; via &lt;a href="https://unsplash.com/s/photos/kite?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt; for the cover photo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://github.com/pagekite/PyPagekite/tree/main/doc"&gt;Pagekite README&lt;/a&gt; is more complete than their website&lt;/li&gt;
&lt;li&gt;Pagekite's &lt;a href="https://pagekite.net/wiki/Floss/TechnicalManual/"&gt;technical manual&lt;/a&gt; (i.e. manpage)&lt;/li&gt;
&lt;li&gt;Certbot (LetsEncrypt) &lt;a href="https://certbot.eff.org/docs/using.html"&gt;user guide&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>pagekite</category>
      <category>linux</category>
      <category>tutorial</category>
      <category>ngrok</category>
    </item>
  </channel>
</rss>
