diff --git a/Dockerfile b/Dockerfile
index 98d3cfc5..2f49d091 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,4 +29,6 @@ COPY --from=builder /app/init ./dist/init
COPY config.example.yml ./dist/config.example.yml
COPY server/db/names.json ./dist/names.json
+COPY public ./public
+
CMD ["npm", "start"]
diff --git a/README.md b/README.md
index 8a5d8b5e..694a25cd 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Pangolin
-Pangolin is a self-hosted tunneled reverse proxy management server with identity and access management, designed to securely expose private resources through use with the Traefik reverse proxy and Wireguard tunnel clients like Newt. With Pangolin, you retain full control over your infrastructure while providing a user-friendly and feature-rich solution for managing proxies, authentication, and access, and simplifying complex network setups, all with a clean and simple UI.
+Pangolin is a self-hosted tunneled reverse proxy management server with identity and access management, designed to securely expose private resources through use with the Traefik reverse proxy and WireGuard tunnel clients like Newt. With Pangolin, you retain full control over your infrastructure while providing a user-friendly and feature-rich solution for managing proxies, authentication, and access, and simplifying complex network setups, all with a clean and simple UI.
### Installation and Documentation
@@ -9,7 +9,7 @@ Pangolin is a self-hosted tunneled reverse proxy management server with identity
## Preview
-
+
_Sites page of Pangolin showing multiple site-to-site tunnels connected to the central server._
@@ -25,6 +25,7 @@ _Sites page of Pangolin showing multiple site-to-site tunnels connected to the c
### Identity & Access Management
- Centralized authentication system using platform SSO. **Users will only have to manage one login.**
+- Totp with backup codes for two-factor authentication.
- Create organizations, each with multiple sites, users, and roles.
- **Role-based access control** to manage resource access permissions.
- Additional authentication options include:
@@ -38,6 +39,7 @@ _Sites page of Pangolin showing multiple site-to-site tunnels connected to the c
- Manage sites, users, and roles with a clean and intuitive UI.
- Monitor site usage and connectivity.
- Light and dark mode options.
+- Mobile friendly.
### Easy Deployment
diff --git a/package.json b/package.json
index 483d5e19..14beebbd 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"db:push": "npx tsx server/db/migrate.ts",
"db:studio": "drizzle-kit studio",
"build": "mkdir -p dist && next build && node esbuild.mjs -e server/index.ts -o dist/server.mjs && node esbuild.mjs -e server/setup/migrations.ts -o dist/migrations.mjs",
- "start": "NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'",
+ "start": "NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'",
"email": "email dev --dir server/emails/templates --port 3005"
},
"dependencies": {
diff --git a/public/logo/pangolin_black.svg b/public/logo/pangolin_black.svg
new file mode 100644
index 00000000..fd2b02ac
--- /dev/null
+++ b/public/logo/pangolin_black.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/public/logo/pangolin_orange.svg b/public/logo/pangolin_orange.svg
new file mode 100644
index 00000000..a8823c9d
--- /dev/null
+++ b/public/logo/pangolin_orange.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/public/screenshots/auth.png b/public/screenshots/auth.png
index 4c7f5889..1bcc35e6 100644
Binary files a/public/screenshots/auth.png and b/public/screenshots/auth.png differ
diff --git a/public/screenshots/connectivity.png b/public/screenshots/connectivity.png
index 7130d19b..7b6ca88d 100644
Binary files a/public/screenshots/connectivity.png and b/public/screenshots/connectivity.png differ
diff --git a/public/screenshots/preview.png b/public/screenshots/preview.png
deleted file mode 100644
index 1c780df3..00000000
Binary files a/public/screenshots/preview.png and /dev/null differ
diff --git a/public/screenshots/share-link.png b/public/screenshots/share-link.png
index b5027e88..7515c8fe 100644
Binary files a/public/screenshots/share-link.png and b/public/screenshots/share-link.png differ
diff --git a/public/screenshots/sites.png b/public/screenshots/sites.png
index 0ca84065..eb82212f 100644
Binary files a/public/screenshots/sites.png and b/public/screenshots/sites.png differ
diff --git a/public/screenshots/users.png b/public/screenshots/users.png
index a6ee97c0..08a8f591 100644
Binary files a/public/screenshots/users.png and b/public/screenshots/users.png differ
diff --git a/server/db/names.ts b/server/db/names.ts
index a0b37ef7..6976d64a 100644
--- a/server/db/names.ts
+++ b/server/db/names.ts
@@ -9,7 +9,7 @@ import { __DIRNAME } from "@server/lib/consts";
const dev = process.env.ENVIRONMENT !== "prod";
let file;
if (!dev) {
- file = join("names.json");
+ file = join(__DIRNAME, "names.json");
} else {
file = join("server/db/names.json");
}
diff --git a/server/emails/sendEmail.ts b/server/emails/sendEmail.ts
index 9a993b24..d7a59608 100644
--- a/server/emails/sendEmail.ts
+++ b/server/emails/sendEmail.ts
@@ -26,7 +26,7 @@ export async function sendEmail(
await emailClient.sendMail({
from: {
- name: opts.name || "Pangolin Proxy",
+ name: opts.name || "Pangolin",
address: opts.from,
},
to: opts.to,
diff --git a/server/emails/templates/NotifyResetPassword.tsx b/server/emails/templates/NotifyResetPassword.tsx
index 98f2522e..9b136924 100644
--- a/server/emails/templates/NotifyResetPassword.tsx
+++ b/server/emails/templates/NotifyResetPassword.tsx
@@ -1,16 +1,20 @@
import {
Body,
- Container,
Head,
- Heading,
Html,
Preview,
- Section,
- Text,
Tailwind
} from "@react-email/components";
import * as React from "react";
-import LetterHead from "./components/LetterHead";
+import { themeColors } from "./lib/theme";
+import {
+ EmailContainer,
+ EmailFooter,
+ EmailGreeting,
+ EmailHeading,
+ EmailLetterHead,
+ EmailText
+} from "./components/Email";
interface Props {
email: string;
@@ -23,41 +27,31 @@ export const ConfirmPasswordReset = ({ email }: Props) => {