Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vandot committed Mar 24, 2023
0 parents commit 802ab96
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 0 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Release

on:
push:
branches-ignore:
- '**'
tags:
- '*.*.*'

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Nim
uses: iffy/install-nim@v4.2.0
- name: Install nimxc
run: |
nimble install -y https://github.com/iffy/nimxc.git
- name: Build Linux
run: |
nimble build -r -d:release --opt:size
mv build/lodev{,-linux-amd64}
- name: Build Darwin
run: |
nimxc c --target=macosx-arm64 -d:release -d:NimblePkgVersion:$(nimble --silent version) --opt:size --out:./build/lodev-darwin-arm64 -f src/lodev.nim
nimxc c --target=macosx-amd64 -d:release -d:NimblePkgVersion:$(nimble --silent version) --opt:size --out:./build/lodev-darwin-amd64 -f src/lodev.nim
- name: Build Windows
run: |
nimxc c --target=windows-amd64 -d:release -d:NimblePkgVersion:$(nimble --silent version) --opt:size --out:./build/lodev-windows-amd64.exe -f src/lodev.nim
- name: Create packages
run: |
tar czf ./build/lodev-linux-amd64.tar.gz --directory=./build lodev-linux-amd64
tar czf ./build/lodev-darwin-amd64.tar.gz --directory=./build lodev-darwin-amd64
tar czf ./build/lodev-darwin-arm64.tar.gz --directory=./build lodev-darwin-arm64
7z a ./build/lodev-windows-amd64.zip ./build/lodev-windows-amd64.exe
- name: Publish release
uses: softprops/action-gh-release@v1
if: success()
with:
files: build/*
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2022, vandot
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# lodev
lodev is as simple proxy server for local development with SSL termination.

Obsoletes using ngrok or manually configuring combination of mkcert, dnsmasq and nginx/caddy. It provides HTTPS endpoint under `https://dev.lo` and by default proxies all requests to `http://127.0.0.1:3000`.

It uses [locert](https://github.com/vandot/locert) to generate and install locally trusted SSL certs and [lodns](https://github.com/vandot/lodns) for DNS name resolution.

## Installation
Download correct binary from the latest [release](https://github.com/vandot/lodev/releases) and place it somewhere in the PATH.

Or `nimble install https://github.com/vandot/lodev`

## Configuration
lodev comes preconfigured for all supported platforms to act as a HTTPS reverse proxy server behind `dev.lo` domain.

On MacOS and Linux you have to run with `sudo` to be able to configure the system
```
sudo lodev install
```
On Windows run inside elevated command prompt or Powershell
```
lodev.exe install
```

## Start
Service must be started with elevated priviledges because it will bind to a well-known port `443`. By default service will proxy all requests to `127.0.0.1:3000`. You can specify different destination port using `-p=8000`.

On MacOS and Linux
```
sudo lodev start
```
On Windows inside elevated command prompt or Powershell
```
lodev.exe start
```

## Uninstallation
On MacOS and Linux run
```
sudo lodev uninstall
```
On Windows run inside elevated command prompt or Powershell
```
lodev.exe uninstall
```
and remove the binary.

## License

BSD 3-Clause License
Binary file added build/lodev
Binary file not shown.
Binary file added build/lodev-darwin-arm64
Binary file not shown.
Binary file added build/lodev-linux-amd64
Binary file not shown.
Binary file added build/lodev-macosx-arm64
Binary file not shown.
Binary file added build/lodev-windows-amd64
Binary file not shown.
1 change: 1 addition & 0 deletions config.nims
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--threads:on
43 changes: 43 additions & 0 deletions lodev.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Package

version = "0.1.0"
author = "vandot"
description = "Simple proxy server for local development"
license = "MIT"
srcDir = "src"
bin = @["lodev"]

binDir = "build"

skipDirs = @[
".github",
]

# Dependencies
requires "nim >= 1.6.6"
requires "chronos"
requires "https://github.com/vandot/lodns#head"
requires "https://github.com/vandot/locert#head"

# Tasks
proc updateNimbleVersion(ver: string) =
let fname = currentSourcePath()
let txt = readFile(fname)
var lines = txt.split("\n")
for i, line in lines:
if line.startsWith("version"):
let s = line.find('"')
let e = line.find('"', s+1)
lines[i] = line[0..s] & ver & line[e..<line.len]
break
writeFile(fname, lines.join("\n"))

task version, "update version":
# last params as version
let ver = paramStr( paramCount() )
if ver == "version":
# print current version
echo version
else:
withDir thisDir():
updateNimbleVersion(ver)
84 changes: 84 additions & 0 deletions src/lodev.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import std/[os, parseopt, strutils]
import pkg/lodnspkg/[actions, server]
import pkg/locertpkg/actions as certActions
import threadpool
import chronos

import ./lodev/[proxy]

const tld = "lo"


proc writeVersion(): string =
const NimblePkgVersion {.strdefine.} = "dev"
result = getAppFilename().extractFilename() & "-" & NimblePkgVersion

proc writeHelp() =
echo writeVersion()
echo """
Run local reverse proxy server with SSL termination
and custom DNS resolver.
install : install system files
uninstall : uninstall system files
start : start service
-p, --port : target port [default 3000]
-h, --help : show help
-v, --version : show version
"""
quit()

proc main() =
var
start = false
dnsIp :string
dnsPort :int
targetIp = "127.0.0.1"
targetPort = Port(3000)

for kind, key, value in getOpt():
case kind
of cmdArgument:
case key
of "install":
(dnsIp, dnsPort) = actions.systemProbe()
certActions.installCA("dev." & tld, true)
actions.install(dnsIp, dnsPort, tld)
of "start":
start = true
of "uninstall":
certActions.uninstallCA(true)
actions.uninstall(tld)
else:
echo "unknown argument: ", key
writeHelp()
of cmdLongOption, cmdShortOption:
case key
of "p", "port":
if value == "":
echo "use '=' to specify port -p=3000 or --port=3000"
quit(1)
targetPort = Port(parseInt(value))
of "v", "version":
echo writeVersion()
quit()
of "h", "help":
writeHelp()
else:
echo "unknown option: ", key
writeHelp()
of cmdEnd:
discard

if start:
(dnsIp, dnsPort) = actions.systemProbe()
var cert = certActions.getCert(true)
let secureProxy = ProxyServer(targetHost: targetIp, targetPort: targetPort, serverIdent: writeVersion(), cert: cert)
let proxyServer = createServer(secureProxy)
spawn server.serve(dnsIp, dnsPort, tld)
proxyServer.start()
waitFor proxyServer.join()
sync()

when isMainModule:
main()
56 changes: 56 additions & 0 deletions src/lodev/helpers.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import httputils, times

proc fromInt*(code: int): HttpCode =
## Returns ``code`` as HttpCode value.
case code
of 100: return Http100
of 101: return Http101
of 200: return Http200
of 201: return Http201
of 202: return Http202
of 203: return Http203
of 204: return Http204
of 205: return Http205
of 206: return Http206
of 300: return Http300
of 301: return Http301
of 302: return Http302
of 303: return Http303
of 304: return Http304
of 305: return Http305
of 307: return Http307
of 400: return Http400
of 401: return Http401
of 403: return Http403
of 404: return Http404
of 405: return Http405
of 406: return Http406
of 407: return Http407
of 408: return Http408
of 409: return Http409
of 410: return Http410
of 411: return Http411
of 412: return Http412
of 413: return Http413
of 414: return Http414
of 415: return Http415
of 416: return Http416
of 417: return Http417
of 418: return Http418
of 421: return Http421
of 422: return Http422
of 426: return Http426
of 428: return Http428
of 429: return Http429
of 431: return Http431
of 451: return Http451
of 500: return Http500
of 501: return Http501
of 502: return Http502
of 503: return Http503
of 504: return Http504
of 505: return Http505
else: return Http505

proc datetime*(): string =
result = "[" & getDateStr() & "T" & getClockStr() & "] "

0 comments on commit 802ab96

Please sign in to comment.