Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.evault
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,5 @@ WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
EXPOSE 4000
workdir /app/infrastructure/evault-core
WORKDIR /app/infrastructure/evault-core
CMD ["pnpm", "dev"]
24 changes: 24 additions & 0 deletions docker/Dockerfile.evault-prod
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
FROM node:22-slim AS deps
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
RUN npm i -g corepack@latest
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm turbo prune evault-core --docker --use-gitignore=false
RUN mkdir /out
RUN cp -R ./out/full/* /out/
RUN cp -R ./out/json/* /out/
RUN cp ./out/pnpm-lock.yaml /out/pnpm-lock.yaml
RUN cp -R node_modules/ /out/


FROM node:22-slim AS core-api
WORKDIR /app
RUN npm i -g corepack@latest
COPY --from=deps /out/ /app
RUN pnpm -F=evault-core build
EXPOSE 4000
WORKDIR /app/infrastructure/evault-core
CMD ["echo \'hi'\"]
3 changes: 2 additions & 1 deletion infrastructure/evault-core/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,8 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"build": "tsc",
"dev": "node --watch --import tsx src/evault.ts"
"dev": "node --watch --import tsx src/evault.ts",
"start": "node ./dist/evault.js"
},
"packageManager": "pnpm@10.6.5",
"keywords": [],
Expand Down
8 changes: 4 additions & 4 deletions infrastructure/evault-core/src/evault.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,10 +32,10 @@ class EVault {
}

start() {
const port = process.env.PORT ?? 4000;
this.server.listen(port, () => {
console.log(`GraphQL Server started on http://localhost:${port}`);
console.log(`Voyager started on http://localhost:${port}`);
const port = process.env.NOMAD_PORT_http || process.env.PORT || 4000;
this.server.listen(Number(port), "0.0.0.0", () => {
console.log(`GraphQL Server started on http://0.0.0.0:${port}`);
console.log(`Voyager started on http://0.0.0.0:${port}`);
});
}
}
Expand Down
41 changes: 25 additions & 16 deletions infrastructure/evault-core/tsconfig.json
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"target": "ES2021",
"module": "CommonJS",
"lib": [
"ESNext",
"DOM"
],
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"*/**/*.spec.ts"
]
}
188 changes: 188 additions & 0 deletions infrastructure/evault-provisioner/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
# Evault Provisioner

A TypeScript API for provisioning evault instances on Nomad. This service allows you to spin up evault instances with Neo4j backends for different tenants.

## Prerequisites

- Node.js 18+
- Docker
- Nomad (see setup instructions below)
- OrbStack (for macOS users)

## Nomad Setup

### macOS Setup (using OrbStack)

Due to CNI bridge plugin requirements, running Nomad on macOS is best done through OrbStack:

1. Install OrbStack: https://orbstack.dev/
2. Create a new VM in OrbStack
3. SSH into the VM and install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

4. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

### Linux Setup

1. Install Nomad:

```bash
# Install Nomad
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install nomad

# Install CNI plugins
sudo mkdir -p /opt/cni/bin
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz | sudo tar -C /opt/cni/bin -xz
```

2. Start Nomad in dev mode:

```bash
sudo nomad agent -dev -network-interface=eth0 -log-level=DEBUG -bind=0.0.0.0
```

## Project Setup

1. Install dependencies:

```bash
npm install
```

2. Build the project:

```bash
npm run build
```

3. Start the server:

```bash
npm start
```

For development with auto-reload:

```bash
npm run dev
```

## API Endpoints

### Health Check

```
GET /health
```

Returns the health status of the API.

### Provision Evault

```
POST /provision
```

Provisions a new evault instance for a tenant.

Request body:

```json
{
"tenantId": "your-tenant-id"
}
```

Response:

```json
{
"success": true,
"message": "Successfully provisioned evault for tenant your-tenant-id",
"jobName": "evault-your-tenant-id"
}
```

## Architecture

The provisioner creates a Nomad job that consists of two tasks:

1. **Neo4j Task**:

- Runs Neo4j 5.15
- Exposes ports: 7687 (bolt) and 7474 (browser)
- Uses dynamic ports for flexibility
- 2GB memory allocation

2. **Evault Task**:
- Runs the evault application
- Connects to Neo4j via localhost
- Uses dynamic port allocation
- 512MB memory allocation
- Depends on Neo4j task

## Environment Variables

- `PORT` - Port to run the API on (default: 3000)
- `NOMAD_ADDR` - Nomad API address (default: http://localhost:4646)

## Troubleshooting

### Common Issues

1. **Port Allocation Issues**:

- Ensure Nomad is running with CNI plugins installed
- Check that the network interface is correctly specified
- Verify that ports are not already in use

2. **Container Networking**:

- Ensure Docker is running
- Check that the bridge network is properly configured
- Verify container-to-container communication

3. **Nomad Job Failures**:
- Check Nomad logs for detailed error messages
- Verify that all required images are available
- Ensure resource allocations are sufficient

### Debugging

To debug Nomad issues:

```bash
# View Nomad logs
journalctl -u nomad -f

# Check Nomad status
nomad status

# View specific job details
nomad job status evault-<tenant-id>

# View allocation details
nomad alloc status <allocation-id>
```

## Development

The project uses TypeScript for type safety and better development experience. The source files are in the `src` directory and are compiled to the `dist` directory.

For development, you can use `npm run dev` which uses `tsx` to run the TypeScript files directly without compilation.
27 changes: 27 additions & 0 deletions infrastructure/evault-provisioner/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"name": "evault-provisioner",
"version": "1.0.0",
"description": "API for provisioning evault instances on Nomad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"test": "vitest"
},
"dependencies": {
"express": "^4.18.2",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"w3id": "workspace:*"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.24",
"nodemon": "^3.0.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^1.3.1"
}
}
Loading