Tunely is a tunneling service similar to ngrok, designed to expose local servers to the internet securely and easily. It consists of three main components: a React-based frontend, a Node.js backend with MongoDB, and a CLI tool. The project leverages AWS (S3, EC2, CloudFront, Route 53) and frp (Fast Reverse Proxy) for deployment and tunneling.
Tunely allows users to:
- Register and log in via a web interface to obtain an authentication token.
- Use the token with a CLI to create tunnels for local servers.
- Access their local servers via unique subdomains (e.g.,
https://abc123.tunely.snapstay.in
).
- Frontend: User interface for registration, login, and token management.
- Deployed at:
https://app.tunely.snapstay.in
- Deployed at:
- Backend: API for authentication and tunnel subdomain generation.
- Deployed at:
https://api.tunely.snapstay.in
- Deployed at:
- CLI: Command-line tool to save tokens and create tunnels.
- npm package:
tunely
- npm package:
- Modern, responsive frontend with AntD, Tailwind CSS, and Bootstrap 5.
- Secure backend with JWT authentication, password hashing, and MongoDB storage.
- Easy-to-use CLI for tunneling local servers with frp.
- HTTPS support across all domains using Let’s Encrypt.
- Node.js and npm installed (download from nodejs.org).
- MongoDB installed locally or a MongoDB Atlas account.
- An AWS account with access to S3, EC2, CloudFront, Route 53, and ACM.
- A domain (e.g.,
snapstay.in
) configured in Route 53. - frp binaries from frp releases).
Follow these steps to set up each component locally:
- Navigate to Frontend Directory:
cd tunely-frontend
- Install Dependencies:
npm install
- Run Locally:
npm start
- Opens at
http://localhost:3000
.
- Opens at
- Navigate to Backend Directory:
cd tunely-backend
- Install Dependencies:
npm install
- Set Up Environment Variables:
- Create a
.env
file:PORT=3000 MONGO_URI=mongodb://localhost:27017/tunely JWT_SECRET=your_jwt_secret_key_here
- Replace
MONGO_URI
andJWT_SECRET
with your values.
- Create a
- Run MongoDB (if local):
mongod
- Run the Server:
npm start
- Runs at
http://localhost:3000
.
- Runs at
- Navigate to CLI Directory:
cd tunely-cli
- Install Dependencies:
npm install
- Add frp Binaries:
- Download
frpc
for your OS (Linux:frpc-linux
, macOS:frpc-mac
, Windows:frpc-windows.exe
). - Place them in
tunely-cli/
. - For Linux/macOS:
chmod +x frpc-linux frpc-mac
- Download
- Link Locally:
npm link
Deploy each component to AWS for production use.
- Build the Frontend:
cd tunely-frontend npm run build
- Upload to S3:
- Create an S3 bucket (
tunely-frontend
):aws s3 sync build/ s3://tunely-frontend --acl public-read
- Create an S3 bucket (
- Set Up CloudFront:
- Create a distribution with origin
tunely-frontend.s3.amazonaws.com
. - Add CNAME
app.tunely.snapstay.in
. - Use an ACM certificate for HTTPS.
- Note the CloudFront domain (e.g.,
d123456789.cloudfront.net
).
- Create a distribution with origin
- Update Route 53:
- A record:
app.tunely.snapstay.in
→ CloudFront domain. - URL:
https://app.tunely.snapstay.in
.
- A record:
- Launch EC2 Instance:
- Use Ubuntu (t2.micro).
- Open ports: 3000, 80, 443, 7000.
- Upload Backend:
scp -r tunely-backend/ ubuntu@<ec2-public-ip>:/home/ubuntu/tunely-backend
- Set Up EC2:
ssh ubuntu@<ec2-public-ip> sudo apt update sudo apt install -y mongodb sudo systemctl start mongodb curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - sudo apt install -y nodejs sudo npm install -g pm2 cd tunely-backend npm install pm2 start index.js
- Set Up frp Server:
wget https://github.com/fatedier/frp/releases/download/v0.58.1/frp_0.58.1_linux_amd64.tar.gz tar -xzf frp_0.58.1_linux_amd64.tar.gz sudo mv frp_0.58.1_linux_amd64/frps /usr/local/bin/
- Create
frps.ini
:[common] bind_port = 7000 vhost_http_port = 8080 subdomain_host = tunely.snapstay.in token = your_global_frp_token
- Run:
pm2 start frps -- -c frps.ini
.
- Create
- Set Up Nginx:
sudo apt install -y nginx
- Create
/etc/nginx/sites-available/api
:server { listen 80; server_name api.tunely.snapstay.in; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
- Create
/etc/nginx/sites-available/tunnel
:server { listen 80; server_name ~^(?<subdomain>.+)\.tunely\.snapstay\.in$; location / { proxy_pass http://localhost:8080; proxy_set_header Host $subdomain.tunely.snapstay.in; proxy_set_header X-Real-IP $remote_addr; } }
- Enable and restart:
sudo ln -s /etc/nginx/sites-available/api /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/tunnel /etc/nginx/sites-enabled/ sudo systemctl restart nginx
- Create
- Add HTTPS:
sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d api.tunely.snapstay.in sudo certbot certonly --manual --preferred-challenges=dns -d "*.tunely.snapstay.in"
- Follow DNS validation steps for the wildcard certificate.
- Update Route 53:
- A record:
api.tunely.snapstay.in
→<ec2-public-ip>
. - A record:
*.tunely.snapstay.in
→<ec2-public-ip>
.
- A record:
- Build and Publish:
cd tunely-cli npm install npm publish --access public
- Install Globally:
npm install -g tunely
-
Frontend:
- Visit
https://app.tunely.snapstay.in
. - Register or log in to get a token.
- View the token on
/dashboard
.
- Visit
-
Backend:
- Test APIs with curl/Postman:
- Register:
POST https://api.tunely.snapstay.in/api/register
with{ "email": "test@example.com", "password": "password123" }
. - Login:
POST https://api.tunely.snapstay.in/api/login
with same payload. - Tunnel:
POST https://api.tunely.snapstay.in/api/tunnel
withAuthorization: Bearer <token>
.
- Register:
- Test APIs with curl/Postman:
-
CLI:
- Save token:
tunely authtoken <your-token>
- Expose server:
tunely http 3000
- Access at
https://abc123.tunely.snapstay.in
.
- Save token:
tunely-frontend/
├── public/
│ ├── index.html
│ ├── favicon.ico
├── src/
│ ├── components/
│ │ ├── Navbar.js
│ │ ├── AuthForm.js
│ │ └── Dashboard.js
│ ├── pages/
│ │ ├── Home.js
│ │ ├── Login.js
│ │ └── Register.js
│ ├── styles/
│ │ └── GlobalStyles.js
│ ├── App.js
│ └── index.js
├── package.json
├── tailwind.config.js
tunely-backend/
├── config/
│ └── db.js
├── middleware/
│ └── auth.js
├── models/
│ ├── User.js
│ └── Tunnel.js
├── routes/
│ ├── auth.js
│ └── tunnel.js
├── .env
├── index.js
├── package.json
tunely-cli/
├── bin/
│ └── tunely.js
├── lib/
│ ├── config.js
│ ├── tunnel.js
│ └── utils.js
├── frpc-linux
├── frpc-mac
├── frpc-windows.exe
├── index.js
├── package.json
- Frontend: React, Ant Design, Tailwind CSS, Bootstrap 5, AWS S3, CloudFront.
- Backend: Node.js, Express.js, MongoDB, Mongoose, bcryptjs, jsonwebtoken, AWS EC2, Nginx.
- CLI: Node.js, Commander.js, axios, ini, child_process, fs-extra, frp.
- Frontend: Ensure backend API (
https://api.tunely.snapstay.in
) is running for login/register. - Backend: Check MongoDB connection and Nginx logs (
/var/log/nginx/error.log
). - CLI: Verify frpc binaries are present and executable; ensure token is saved.
Submit pull requests or issues to improve any component. Test locally before deploying changes.
MIT License - free to use and modify as needed.
---
### Notes
- This combined README assumes a project directory structure with `tunely-frontend/`, `tunely-backend/`, and `tunely-cli/` as subdirectories.
- It’s beginner-friendly with detailed steps, commands, and explanations.
- Replace `<repository-url>` and `<ec2-public-ip>` with your actual values.
- The frp token (`your_global_frp_token`) should match across the backend (`frps.ini`) and CLI (`tunnel.js`).