-
Notifications
You must be signed in to change notification settings - Fork 0
docs: Extend security and installation docs #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 2 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,7 @@ | ||
| { | ||
| "editor.formatOnSave": true, | ||
| "editor.defaultFormatter": "oxc.oxc-vscode" | ||
| "editor.defaultFormatter": "oxc.oxc-vscode", | ||
| "[typescriptreact]": { | ||
| "editor.defaultFormatter": "oxc.oxc-vscode" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "$schema": "node_modules/@fumadocs/cli/dist/schema.json", | ||
| "aliases": { | ||
| "uiDir": "./components/ui", | ||
| "componentsDir": "./components", | ||
| "layoutDir": "./layouts", | ||
| "cssDir": "./styles", | ||
| "libDir": "./lib" | ||
| }, | ||
| "baseDir": "src", | ||
| "uiLibrary": "radix-ui", | ||
| "framework": "tanstack-start", | ||
| "commands": {} | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,20 @@ | ||
| --- | ||
| title: Security | ||
| description: Secure your OrcaCD deployment with hardening | ||
| description: Secure your OrcaCD deployment | ||
| --- | ||
|
|
||
| TODO: | ||
| OrcaCD is designed to be safe by default, but of course, there are always additional steps you can take to further secure your deployment. Here are some best practices to consider: | ||
|
|
||
| ## Harden your Deployment | ||
|
|
||
| - Disable password authentication for the Hub and use a secure OIDC provider instead, that enforces strong authentication methods, including secure multi-factor authentication (MFA). | ||
| - Always run the hub behind a secure reverse proxy and ensure that all communicationis encrypted using TLS. | ||
| - Make sure to configure the `TRUSTED_PROXIES` environment variable correctly to prevent IP spoofing attacks. | ||
|
|
||
| ## Why is it safe by default? | ||
|
|
||
| A big focus of OrcaCD next to ease of use is security. Here are some of the measures we have taken to achieve this: | ||
|
|
||
| - All sensitive data is stored encrypted in the database using a modern encryption algorithm ([AEGIS-256](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-aegis-aead-18)). | ||
| - Messages between the Hub and the Agents are encrypted with the same algorithm. The key is computed using the quantum-resistant [ML-KEM](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf) algorithm in combination with [X25519](https://www.rfc-editor.org/rfc/rfc7748.html). | ||
| - We take all security issues seriously. You can find our security policy [here](https://github.com/OrcaCD/orca-cd/blob/main/SECURITY.md). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,72 @@ | ||
| --- | ||
| title: Installation | ||
| description: Get OrcaCD running quickly with Docker installation | ||
| description: Get OrcaCD running quickly with Docker | ||
| --- | ||
|
|
||
| ## Installation with Docker | ||
| import { Step, Steps } from "fumadocs-ui/components/steps"; | ||
|
timokoessler marked this conversation as resolved.
Outdated
|
||
| import { Tab, Tabs } from "fumadocs-ui/components/tabs"; | ||
|
timokoessler marked this conversation as resolved.
Outdated
|
||
|
|
||
| 1. Download the [`docker-compose.yml`](https://raw.githubusercontent.com/OrcaCD/orca-cd/main/docker-compose.yml) and [`.env`](https://raw.githubusercontent.com/OrcaCD/orca-cd/main/.env.example) file: | ||
| <Steps> | ||
| <Step> | ||
|
|
||
| ```bash | ||
| ## Start Hub and Agent | ||
|
|
||
| Download the [`docker-compose.yml`](https://raw.githubusercontent.com/OrcaCD/orca-cd/main/docker-compose.yml) and [`.env`](https://raw.githubusercontent.com/OrcaCD/orca-cd/main/.env.example) file: | ||
|
|
||
| ```bash tab="curl" | ||
| curl -o docker-compose.yml https://raw.githubusercontent.com/OrcaCD/orca-cd/main/docker-compose.yml | ||
| curl -o .env https://raw.githubusercontent.com/OrcaCD/orca-cd/main/.env.example | ||
| ``` | ||
|
|
||
| 2. Edit the `.env` file so that it fits your needs. See the environment variables section for more information. | ||
| ```bash tab="wget" | ||
| wget -O docker-compose.yml https://raw.githubusercontent.com/OrcaCD/orca-cd/main/docker-compose.yml | ||
| wget -O .env https://raw.githubusercontent.com/OrcaCD/orca-cd/main/.env.example | ||
| ``` | ||
|
|
||
| Edit the `.env` file according to the instructions in the file. You can also customize other environment variables as needed. | ||
| See the [environment variables page](../configuration/env-variables) for more details. | ||
|
|
||
| <Callout> | ||
| Remove the Agent part from the compose file if you don't want to deploy it to the same machine as | ||
| the Hub. | ||
| </Callout> | ||
|
|
||
| Start the Hub and the Agent: | ||
|
|
||
| ```bash | ||
| docker compose up -d | ||
| ``` | ||
|
|
||
| </Step> | ||
| <Step> | ||
|
|
||
| 3. Run `docker compose up -d` | ||
| ## Configure your Reverse Proxy | ||
|
|
||
| See the [reverse proxy guide](../guides/reverse-proxy) for instructions on how to configure a reverse proxy for your Hub. | ||
|
|
||
| </Step> | ||
| <Step> | ||
|
|
||
| ## Create an Admin Account | ||
|
|
||
| Create an admin account on `https://<your-app-url>/login` | ||
|
|
||
| Todo: Add image | ||
|
|
||
| </Step> | ||
| <Step> | ||
|
|
||
| ## Connect your first Agent | ||
|
|
||
| Navigate to the Agents page and click "Add Agent". Follow the instructions and copy the token and add it as `AUTH_TOKEN` to the `.env` file of your Agent deployment and restart the Agent. | ||
|
|
||
| Todo: Add image | ||
|
|
||
| </Step> | ||
| <Step> | ||
| ## Start Deploying | ||
|
|
||
| Add your first repository and create your first deployment. | ||
|
|
||
| </Step> | ||
| </Steps> | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import type { ReactNode } from "react"; | ||
|
|
||
| export function Steps({ children }: { children: ReactNode }) { | ||
| return <div className="fd-steps">{children}</div>; | ||
| } | ||
|
|
||
| export function Step({ children }: { children: ReactNode }) { | ||
| return <div className="fd-step">{children}</div>; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| "use client"; | ||
|
|
||
| import * as React from "react"; | ||
| import { | ||
| type ComponentProps, | ||
| createContext, | ||
| type ReactNode, | ||
| useContext, | ||
| useEffect, | ||
| useId, | ||
| useMemo, | ||
| useState, | ||
| } from "react"; | ||
| import { cn } from "../lib/cn"; | ||
| import * as Unstyled from "./ui/tabs"; | ||
|
|
||
| type CollectionKey = string | symbol; | ||
|
|
||
| export interface TabsProps extends Omit< | ||
| ComponentProps<typeof Unstyled.Tabs>, | ||
| "value" | "onValueChange" | ||
| > { | ||
| /** | ||
| * Use simple mode instead of advanced usage as documented in https://radix-ui.com/primitives/docs/components/tabs. | ||
| */ | ||
| items?: string[]; | ||
|
|
||
| /** | ||
| * Shortcut for `defaultValue` when `items` is provided. | ||
| * | ||
| * @defaultValue 0 | ||
| */ | ||
| defaultIndex?: number; | ||
|
|
||
| /** | ||
| * Additional label in tabs list when `items` is provided. | ||
| */ | ||
| label?: ReactNode; | ||
| } | ||
|
|
||
| const TabsContext = createContext<{ | ||
| items?: string[]; | ||
| collection: CollectionKey[]; | ||
| } | null>(null); | ||
|
|
||
| function useTabContext() { | ||
| const ctx = useContext(TabsContext); | ||
| if (!ctx) { | ||
| throw new Error("You must wrap your component in <Tabs>"); | ||
| } | ||
| return ctx; | ||
| } | ||
|
|
||
| export function TabsList(props: React.ComponentPropsWithRef<typeof Unstyled.TabsList>) { | ||
| return ( | ||
| <Unstyled.TabsList | ||
| {...props} | ||
| className={cn( | ||
| "flex gap-3.5 text-fd-secondary-foreground overflow-x-auto px-4 not-prose", | ||
| props.className, | ||
| )} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export function TabsTrigger(props: React.ComponentPropsWithRef<typeof Unstyled.TabsTrigger>) { | ||
| return ( | ||
| <Unstyled.TabsTrigger | ||
| {...props} | ||
| className={cn( | ||
| "inline-flex items-center gap-2 whitespace-nowrap text-fd-muted-foreground border-b border-transparent py-2 text-sm font-medium transition-colors [&_svg]:size-4 hover:text-fd-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-fd-primary data-[state=active]:text-fd-primary", | ||
| props.className, | ||
| )} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export function Tabs({ | ||
| ref, | ||
| className, | ||
| items, | ||
| label, | ||
| defaultIndex = 0, | ||
| defaultValue = items ? escapeValue(items[defaultIndex]) : undefined, | ||
| ...props | ||
| }: TabsProps) { | ||
| const [value, setValue] = useState(defaultValue); | ||
| const collection = useMemo<CollectionKey[]>(() => [], []); | ||
|
|
||
| return ( | ||
| <Unstyled.Tabs | ||
| ref={ref} | ||
| className={cn( | ||
| "flex flex-col overflow-hidden rounded-xl border bg-fd-secondary my-4", | ||
| className, | ||
| )} | ||
| value={value} | ||
| onValueChange={(v: string) => { | ||
| if (items && !items.some((item) => escapeValue(item) === v)) { | ||
| return; | ||
| } | ||
| setValue(v); | ||
| }} | ||
| {...props} | ||
| > | ||
| {items && ( | ||
| <TabsList> | ||
| {label && <span className="text-sm font-medium my-auto me-auto">{label}</span>} | ||
| {items.map((item) => ( | ||
| <TabsTrigger key={item} value={escapeValue(item)}> | ||
| {item} | ||
| </TabsTrigger> | ||
| ))} | ||
| </TabsList> | ||
| )} | ||
| <TabsContext.Provider value={useMemo(() => ({ items, collection }), [collection, items])}> | ||
| {props.children} | ||
| </TabsContext.Provider> | ||
| </Unstyled.Tabs> | ||
| ); | ||
| } | ||
|
|
||
| export interface TabProps extends Omit<ComponentProps<typeof Unstyled.TabsContent>, "value"> { | ||
| /** | ||
| * Value of tab, detect from index if unspecified. | ||
| */ | ||
| value?: string; | ||
| } | ||
|
|
||
| export function Tab({ value, ...props }: TabProps) { | ||
| const { items } = useTabContext(); | ||
| const resolved = | ||
| value ?? | ||
| // eslint-disable-next-line react-hooks/rules-of-hooks -- `value` is not supposed to change | ||
| items?.at(useCollectionIndex()); | ||
| if (!resolved) { | ||
| throw new Error( | ||
| "Failed to resolve tab `value`, please pass a `value` prop to the Tab component.", | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <TabsContent value={escapeValue(resolved)} {...props}> | ||
| {props.children} | ||
| </TabsContent> | ||
| ); | ||
| } | ||
|
|
||
| export function TabsContent({ | ||
| value, | ||
| className, | ||
| ...props | ||
| }: ComponentProps<typeof Unstyled.TabsContent>) { | ||
| return ( | ||
| <Unstyled.TabsContent | ||
| value={value} | ||
| forceMount | ||
| className={cn( | ||
| "p-4 text-[0.9375rem] bg-fd-background rounded-xl outline-none prose-no-margin data-[state=inactive]:hidden [&>figure:only-child]:-m-4 [&>figure:only-child]:border-none", | ||
| className, | ||
| )} | ||
| {...props} | ||
| > | ||
| {props.children} | ||
| </Unstyled.TabsContent> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Inspired by Headless UI. | ||
| * | ||
| * Return the index of children, this is made possible by registering the order of render from children using React context. | ||
| * This is supposed by work with pre-rendering & pure client-side rendering. | ||
| */ | ||
| function useCollectionIndex() { | ||
| const key = useId(); | ||
| const { collection } = useTabContext(); | ||
|
|
||
| useEffect(() => { | ||
| return () => { | ||
| const idx = collection.indexOf(key); | ||
| if (idx !== -1) { | ||
| collection.splice(idx, 1); | ||
| } | ||
| }; | ||
| }, [key, collection]); | ||
|
|
||
| if (!collection.includes(key)) { | ||
| collection.push(key); | ||
| } | ||
| return collection.indexOf(key); | ||
| } | ||
|
|
||
| /** | ||
| * only escape whitespaces in values in simple mode | ||
| */ | ||
| function escapeValue(v: string): string { | ||
| return v.toLowerCase().replace(/\s/, "-"); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.