1
0
mirror of https://github.com/Infisical/infisical.git synced 2025-03-21 20:37:05 +00:00

Compare commits

..

14 Commits

Author SHA1 Message Date
5bb0b7a508 K8s HA reference docs
A complete guide to k8s HA reference docs
2025-01-28 02:53:02 -05:00
1d5b629d8f Merge pull request from akhilmhdh/feat/region-flag
Added region flag for eu in cli
2025-01-22 13:21:14 -05:00
14f895cae2 Merge pull request from Infisical/readme-ssh
Add Infisical SSH to README
2025-01-22 12:56:21 -05:00
=
b7be6bd1d9 feat: removed region flag in description 2025-01-22 14:41:24 +05:30
58a97852f6 Merge pull request from akhilmhdh/fix/pro-trail-btn
fix: resolved pro trial button issue in sidebar
2025-01-22 01:58:32 -05:00
=
980aa9eaae fix: resolved pro trial button issue in sidebar 2025-01-22 12:25:54 +05:30
=
a35d1aa72b feat: removed root flag and added description for domain 2025-01-22 12:18:58 +05:30
52d801bce5 Add Infisical SSH to README 2025-01-21 22:36:55 -08:00
71ca7a82db Merge pull request from Infisical/vercel-project-help-text
Improvement: Vercel Integration Project Permission Helper Text
2025-01-21 21:43:53 -08:00
6cdc71b9b1 Merge pull request from Infisical/fix-org-sidebar-check
Fix: Correct Display Org Sidebar Check
2025-01-22 03:02:43 +01:00
f88d6a183f fix: correct display org sidebar check 2025-01-21 17:46:14 -08:00
fa82d4953e improvement: adjust casing 2025-01-21 16:05:11 -08:00
12d9fe9ffd improvement: add helper text to point vercel users to access permissions if they dont see their project listed 2025-01-21 16:02:24 -08:00
=
d627ecf05d feat: added region flag for eu in cli 2025-01-18 17:05:29 +05:30
9 changed files with 298 additions and 36 deletions
README.md
cli/packages/cmd
docs
cli/commands
mint.json
self-hosting/reference-architectures
frontend/src
components/v2/FormControl
layouts/OrganizationLayout
OrganizationLayout.tsx
components/MinimizedOrgSidebar
pages/secret-manager/integrations/VercelConfigurePage

@ -56,7 +56,7 @@ We're on a mission to make security tooling more accessible to everyone, not jus
- **[Infisical Kubernetes Operator](https://infisical.com/docs/documentation/getting-started/kubernetes)**: Deliver secrets to your Kubernetes workloads and automatically reload deployments.
- **[Infisical Agent](https://infisical.com/docs/infisical-agent/overview)**: Inject secrets into applications without modifying any code logic.
### Internal PKI:
### Infisical (Internal) PKI:
- **[Private Certificate Authority](https://infisical.com/docs/documentation/platform/pki/private-ca)**: Create CA hierarchies, configure [certificate templates](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-issuing-certificates) for policy enforcement, and start issuing X.509 certificates.
- **[Certificate Management](https://infisical.com/docs/documentation/platform/pki/certificates)**: Manage the certificate lifecycle from [issuance](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-issuing-certificates) to [revocation](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-revoking-certificates) with support for CRL.
@ -64,12 +64,17 @@ We're on a mission to make security tooling more accessible to everyone, not jus
- **[Infisical PKI Issuer for Kubernetes](https://infisical.com/docs/documentation/platform/pki/pki-issuer)**: Deliver TLS certificates to your Kubernetes workloads with automatic renewal.
- **[Enrollment over Secure Transport](https://infisical.com/docs/documentation/platform/pki/est)**: Enroll and manage certificates via EST protocol.
### Key Management (KMS):
### Infisical Key Management System (KMS):
- **[Cryptographic Keys](https://infisical.com/docs/documentation/platform/kms)**: Centrally manage keys across projects through a user-friendly interface or via the API.
- **[Encrypt and Decrypt Data](https://infisical.com/docs/documentation/platform/kms#guide-to-encrypting-data)**: Use symmetric keys to encrypt and decrypt data.
### Infisical SSH
- **[Signed SSH Certificates](https://infisical.com/docs/documentation/platform/ssh)**: Issue ephemeral SSH credentials for secure, short-lived, and centralized access to infrastructure.
### General Platform:
- **Authentication Methods**: Authenticate machine identities with Infisical using a cloud-native or platform agnostic authentication method ([Kubernetes Auth](https://infisical.com/docs/documentation/platform/identities/kubernetes-auth), [GCP Auth](https://infisical.com/docs/documentation/platform/identities/gcp-auth), [Azure Auth](https://infisical.com/docs/documentation/platform/identities/azure-auth), [AWS Auth](https://infisical.com/docs/documentation/platform/identities/aws-auth), [OIDC Auth](https://infisical.com/docs/documentation/platform/identities/oidc-auth/general), [Universal Auth](https://infisical.com/docs/documentation/platform/identities/universal-auth)).
- **[Access Controls](https://infisical.com/docs/documentation/platform/access-controls/overview)**: Define advanced authorization controls for users and machine identities with [RBAC](https://infisical.com/docs/documentation/platform/access-controls/role-based-access-controls), [additional privileges](https://infisical.com/docs/documentation/platform/access-controls/additional-privileges), [temporary access](https://infisical.com/docs/documentation/platform/access-controls/temporary-access), [access requests](https://infisical.com/docs/documentation/platform/access-controls/access-requests), [approval workflows](https://infisical.com/docs/documentation/platform/pr-workflows), and more.
- **[Audit logs](https://infisical.com/docs/documentation/platform/audit-logs)**: Track every action taken on the platform.

@ -315,7 +315,11 @@ var loginCmd = &cobra.Command{
credential, err := authStrategies[strategy](cmd, infisicalClient)
if err != nil {
util.HandleError(fmt.Errorf("unable to authenticate with %s [err=%v]", formatAuthMethod(loginMethod), err))
euErrorMessage := ""
if strings.HasPrefix(config.INFISICAL_URL, util.INFISICAL_DEFAULT_US_URL) {
euErrorMessage = fmt.Sprintf("\nIf you are using the Infisical Cloud Europe Region, please switch to it by using the \"--domain %s\" flag.", util.INFISICAL_DEFAULT_EU_URL)
}
util.HandleError(fmt.Errorf("unable to authenticate with %s [err=%v].%s", formatAuthMethod(loginMethod), err, euErrorMessage))
}
if plainOutput {

@ -11,6 +11,7 @@ description: "Infisical CLI command overview"
| `init` | Used to link a local project to the platform. |
| `run` | Used to inject envars from the platform into an application process. |
| `vault` | Used to manage where your login credentials are stored at rest |
## Global options
| Option | Description |

@ -301,7 +301,8 @@
"group": "Reference architectures",
"pages": [
"self-hosting/reference-architectures/aws-ecs",
"self-hosting/reference-architectures/linux-deployment-ha"
"self-hosting/reference-architectures/linux-deployment-ha",
"self-hosting/reference-architectures/on-prem-k8s-ha"
]
},
"self-hosting/ee",

@ -0,0 +1,231 @@
---
title: "Kubernetes (HA)"
description: "Reference architecture for self-hosting Infisical on Kubernetes (HA)"
---
Deploying Infisical on-premise with high availability requires expertise in networking, container orchestration, and database management.
This guide serves as a reference architecture and a starting point. Actual deployments may vary depending on your organization's existing infrastructure and capabilities.
## Architecture Overview
{/* ![On premise architecture](/images/self-hosting/reference-architectures/on-premise-architecture.png) */}
```mermaid
flowchart TB
subgraph GLB["Global LB (HAProxy/NGINX)"]
end
subgraph OS["Object Storage"]
direction LR
store["S3/MinIO/Enterprise Storage"]
subgraph store_contents["Storage Contents"]
wal["PostgreSQL WAL"]
pgbackup["PostgreSQL Backups"]
redisbackup["Redis Backups"]
end
end
subgraph DC1["Active Data Center"]
direction TB
subgraph k8s1["Kubernetes Cluster"]
ing1["Ingress Controller"]
app1["Infisical Deployment"]
subgraph db1["CloudNativePG"]
pg1p["PostgreSQL Primary"]
pg1r["PostgreSQL Replicas"]
end
subgraph red1["Redis (Bitnami)"]
rp1["Redis Primary"]
end
end
end
subgraph DC2["Passive Data Center"]
direction TB
subgraph k8s2["Kubernetes Cluster"]
ing2["Ingress Controller"]
app2["Infisical Deployment"]
subgraph db2["CloudNativePG"]
pg2["PostgreSQL Replicas"]
end
subgraph red2["Redis (Bitnami)"]
r2["Redis Standby"]
end
end
end
%% Connections
GLB --> ing1
GLB -.-> ing2
%% Database connections
pg1p --> store
store --> pg2
%% Redis backup flow
rp1 --> store
store -.-> r2
%% Intra-DC connections
ing1 --> app1
app1 --> db1
app1 --> red1
ing2 --> app2
app2 --> db2
app2 --> red2
classDef primary fill:#f96,stroke:#333
classDef replica fill:#69f,stroke:#333
classDef storage fill:#9c6,stroke:#333
classDef lb fill:#c9f,stroke:#333
class pg1p,rp1 primary
class pg1r,pg2,r2 replica
class store,wal,pgbackup,redisbackup storage
class GLB,ing1,ing2 lb
```
The architecture above makes use of Kubernetes for orchestrating both stateless and stateful components.
The architecture spans multiple data centers for increased redundancy, availability and disaster recovery capabilities using an active-passive configuration.
### Stateful vs stateless workloads
While managing databases within Kubernetes has typically been complex, modern operators like [CloudNativePG](https://cloudnative-pg.io/) simplify this process by handling storage provisioning, persistent volume management, and backup/recovery processes.
However, if you lack deep expertise in Kubernetes operators or database management, we recommend a hybrid approach where the database is on a managed service for production deployments.
<Warning>
Managing stateful components like databases can be challenging without deep expertise or a dedicated in-house database management team.
To simplify operations and reduce complexity, we recommend offloading databases to managed services such as AWS RDS/ElastiCache.
These managed services automatically handle provisioning, scaling, failover, backups and rollbacks.
</Warning>
## Core Components
### Kubernetes Cluster
Infisical is deployed on a Kubernetes cluster, which allows for container management, auto-scaling, and self-healing capabilities.
A load balancer sits in front of the Kubernetes cluster, directing traffic and making sure there is an even load distribution across the application nodes.
This is the entry point where all other services will interact with Infisical.
### Object Storage
The architecture requires S3-compatible object storage for database backups and cross-datacenter replication. This can be provided by:
- Existing enterprise object storage solution
- Dedicated MinIO deployment
- In-cluster MinIO deployment if neither option above is available
The object storage must be accessible from all Kubernetes clusters and provides:
- Storage for PostgreSQL WAL archiving and backups
- Storage for Redis backups
### CloudNativePG for High Availability PostgreSQL
The database layer is powered by PostgreSQL, managed by CloudNativePG operator for high availability:
- **Redundancy:** CloudNativePG manages a primary-replica setup where the primary handles write operations and replicas handle read operations
- **Failover:** The operator automatically handles failover within a cluster by promoting a replica to primary when needed
- **Backup and Recovery:** Built-in support for backup to S3-compatible storage with point-in-time recovery capabilities
### Redis High Availability
Redis is deployed using the [Bitnami Helm chart](https://github.com/bitnami/charts/tree/main/bitnami/redis) in a simple primary configuration:
- Single Redis instance per cluster without streaming replication
- Regular backups to object storage
- Restore from backup during failover
<Note>
Infisical does not support Redis cluster mode, and since this is an active-passive setup, we use a simple Redis deployment with backup/restore for failover.
</Note>
#### PostgreSQL Backup and Restore
PostgreSQL is the single source of truth for nearly all application data on Infisical.
CloudNativePG provides well defined backup and restore capabilities:
- **Continuous Backup:** The operator continuously archives WAL files to object storage
- **Point-in-Time Recovery:** Supports restoring to any point in time using WAL archiving
- **Regular Testing:** Periodically test backup restoration to exercise the full lifecycle of this process
#### Redis Backup and Restore
Each Redis instance is backed up through a Kubernetes CronJob that:
1. Executes the Redis `SAVE` command
2. Copies the resulting `dump.rdb` to object storage
3. Manages backup retention
<Accordion title="Example Redis backup CronJob">
```yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: redis-backup
spec:
schedule: "0 * * * *" # Every hour
jobTemplate:
spec:
template:
spec:
containers:
- name: redis-backup
image: bitnami/redis
command:
- /bin/sh
- -c
- |
redis-cli -a $REDIS_PASSWORD save
mc cp /data/dump.rdb object-store/redis-backups/
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-data
```
</Accordion>
During failover, the latest Redis backup is restored from object storage to the passive data center. This process is manual and requires operator intervention.
## Multi Data Center Deployment
Infisical can be deployed across multiple data centers in an active-passive configuration for disaster recovery. In this setup, one data center serves as the active site while others remain as passive standbys.
### Active Data Center
The active data center contains:
- The primary PostgreSQL cluster managed by CloudNativePG handling all write operations
- The active Redis instance handling all traffic
- The active Infisical deployment serving all user traffic
### Passive Data Centers
Passive data centers act as disaster recovery sites. Each contains:
- A replica PostgreSQL cluster that replicates from the active site's primary cluster
- A standby Redis instance (not receiving traffic)
- A standby Infisical deployment (not receiving traffic)
### Traffic Management and Failover
Traffic routing between data centers requires:
1. A global load balancer for traffic management. For on-premises deployments, this can be implemented using:
- HAProxy or NGINX configured as a global load balancer
- Any enterprise network routing solutions you may already have in place
2. Each data center should have its own ingress or load balancer
The global load balancer should be deployed in a highly available configuration across multiple locations to avoid it becoming a single point of failure.
During normal operation:
- The global load balancer routes all traffic to the active data center
- Replica PostgreSQL clusters continuously replicate from the primary cluster
- Redis backups are regularly created and stored in object storage
During failover:
- A human operator must initiate the failover process
- The operator promotes a replica PostgreSQL cluster in the target passive data center to become primary using CloudNativePG's promotion process
- The latest Redis backup is restored from object storage to the passive data center's Redis instance
- Once database failover is complete, the global load balancer is updated to direct traffic to the new active data center
<Note>
This is an active-passive setup where failover must be initiated manually by an operator. Automatic failover between data centers is not recommended as it can lead to split-brain scenarios. The operator should verify the state of both data centers before initiating failover.
</Note>
## Data Replication Across Data Centers
### PostgreSQL Replication
CloudNativePG manages replication across data centers:
- **Replica Clusters:** Each data center runs a replica cluster that replicates from the primary cluster
- **WAL Shipping:** Changes are replicated via WAL shipping to object storage
- **Failover:** The operator can promote a replica cluster to primary during planned switchovers or failures
### Object Storage Configuration
If using MinIO for object storage, ensure:
- High availability deployment if running dedicated MinIO cluster
- Proper access controls and encryption for data at rest
- Regular monitoring of storage capacity and performance
- Backup of object storage data itself if running your own MinIO deployment

@ -58,7 +58,7 @@ export type FormHelperTextProps = {
export const FormHelperText = ({ isError, text }: FormHelperTextProps) => (
<div
className={twMerge(
"mt-2 flex items-center font-inter text-xs text-mineshaft-300 opacity-90",
"mt-2 flex items-center font-inter text-xs text-mineshaft-300 text-opacity-90",
isError && "text-red-600"
)}
>

@ -32,16 +32,18 @@ export const OrganizationLayout = () => {
const { t } = useTranslation();
const shouldShowOrgSidebar = !(
[
linkOptions({ to: "/organization/secret-manager/overview" }).to,
linkOptions({ to: "/organization/cert-manager/overview" }).to,
linkOptions({ to: "/organization/ssh/overview" }).to,
linkOptions({ to: "/organization/kms/overview" }).to,
linkOptions({ to: "/organization/secret-scanning" }).to,
linkOptions({ to: "/organization/secret-sharing" }).to
] as string[]
).includes(location.pathname);
const shouldShowOrgSidebar =
location.pathname.startsWith("/organization") &&
!(
[
linkOptions({ to: "/organization/secret-manager/overview" }).to,
linkOptions({ to: "/organization/cert-manager/overview" }).to,
linkOptions({ to: "/organization/ssh/overview" }).to,
linkOptions({ to: "/organization/kms/overview" }).to,
linkOptions({ to: "/organization/secret-scanning" }).to,
linkOptions({ to: "/organization/secret-sharing" }).to
] as string[]
).includes(location.pathname);
return (
<>

@ -27,7 +27,8 @@ import {
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger
DropdownMenuTrigger,
Tooltip
} from "@app/components/v2";
import { envConfig } from "@app/config/env";
import { useOrganization, useSubscription, useUser } from "@app/context";
@ -386,26 +387,28 @@ export const MinimizedOrgSidebar = () => {
</DropdownMenuContent>
</DropdownMenu>
{subscription && subscription.slug === "starter" && !subscription.has_used_trial && (
<button
type="button"
onClick={async () => {
if (!subscription || !currentOrg) return;
<Tooltip content="Start Free Pro Trial" side="right">
<button
type="button"
onClick={async () => {
if (!subscription || !currentOrg) return;
// direct user to start pro trial
const url = await mutateAsync({
orgId: currentOrg.id,
success_url: window.location.href
});
// direct user to start pro trial
const url = await mutateAsync({
orgId: currentOrg.id,
success_url: window.location.href
});
window.location.href = url;
}}
className="mt-1.5 w-full"
>
<div className="justify-left mb-1.5 mt-1.5 flex w-full items-center rounded-md bg-mineshaft-600 py-1 pl-4 text-mineshaft-300 duration-200 hover:bg-mineshaft-500 hover:text-primary-400">
<FontAwesomeIcon icon={faInfinity} className="ml-0.5 mr-3 py-2 text-primary" />
Start Free Pro Trial
</div>
</button>
window.location.href = url;
}}
className="mt-1.5 w-full"
>
<div className="justify-left mb-1.5 mt-1.5 flex w-full flex-col items-center rounded-md p-1 text-xs text-mineshaft-300 transition-all duration-150 hover:bg-mineshaft-500 hover:text-primary-400">
<FontAwesomeIcon icon={faInfinity} className="py-2 text-lg text-primary" />
Pro Trial
</div>
</button>
</Tooltip>
)}
<DropdownMenu>
<DropdownMenuTrigger className="w-full" asChild>

@ -16,7 +16,8 @@ import {
FormControl,
Input,
Select,
SelectItem
SelectItem,
Tooltip
} from "@app/components/v2";
import { ROUTE_PATHS } from "@app/const/routes";
import { useWorkspace } from "@app/context";
@ -192,7 +193,21 @@ export const VercelConfigurePage = () => {
placeholder="Provide a path, default is /"
/>
</FormControl>
<FormControl label="Vercel App" className="px-6">
<FormControl
label="Vercel App"
helperText={
<Tooltip
className="max-w-md"
content="Double check Infisical's access permissions in Vercel by navigating to Team > Integrations > Infisical > Settings > Manage Access."
>
<div>
<span>Don&#39;t see the project you&#39;re looking for?</span>{" "}
<FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-400" />
</div>
</Tooltip>
}
className="px-6"
>
<Select
value={targetAppId}
onValueChange={(val) => setTargetAppId(val)}