Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@ weaviate_data/

# Codegate Dashboard DB
codegate.db

# certificate directory
certs/
160 changes: 160 additions & 0 deletions cert_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
from cryptography import x509
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
import datetime
import os

def generate_certificates(cert_dir="certs"):
"""Generate self-signed certificates with proper extensions for HTTPS proxy"""
# Create certificates directory if it doesn't exist
if not os.path.exists(cert_dir):
print("Making: ", cert_dir)
os.makedirs(cert_dir)

# Generate private key
ca_private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096, # Increased key size for better security
)

# Generate public key
ca_public_key = ca_private_key.public_key()

# CA BEGIN
name = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, "Proxy Pilot CA"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Proxy Pilot"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Development"),
x509.NameAttribute(NameOID.COUNTRY_NAME, "UK"),
])

builder = x509.CertificateBuilder()
builder = builder.subject_name(name)
builder = builder.issuer_name(name)
builder = builder.public_key(ca_public_key)
builder = builder.serial_number(x509.random_serial_number())
builder = builder.not_valid_before(datetime.datetime.utcnow())
builder = builder.not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=3650) # 10 years
)

builder = builder.add_extension(
x509.BasicConstraints(ca=True, path_length=None),
critical=True,
)

builder = builder.add_extension(
x509.KeyUsage(
digital_signature=True,
content_commitment=False,
key_encipherment=True,
data_encipherment=False,
key_agreement=False,
key_cert_sign=True, # This is a CA
crl_sign=True,
encipher_only=False,
decipher_only=False
),
critical=True,
)

ca_cert = builder.sign(
private_key=ca_private_key,
algorithm=hashes.SHA256(),
)

# Save CA certificate and key

with open("certs/ca.crt", "wb") as f:
f.write(ca_cert.public_bytes(serialization.Encoding.PEM))

with open("certs/ca.key", "wb") as f:
f.write(ca_private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
# CA END

# SERVER BEGIN

## Generate new certificate for domain
server_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048, # 2048 bits is sufficient for domain certs
)

name = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, "Proxy Pilot CA"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Proxy Pilot Generated"),
])

builder = x509.CertificateBuilder()
builder = builder.subject_name(name)
builder = builder.issuer_name(ca_cert.subject)
builder = builder.public_key(server_key.public_key())
builder = builder.serial_number(x509.random_serial_number())
builder = builder.not_valid_before(datetime.datetime.utcnow())
builder = builder.not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=365)
)

# Add domain to SAN
builder = builder.add_extension(
x509.SubjectAlternativeName([x509.DNSName("localhost")]),
critical=False,
)

# Add extended key usage
builder = builder.add_extension(
x509.ExtendedKeyUsage([
ExtendedKeyUsageOID.SERVER_AUTH,
ExtendedKeyUsageOID.CLIENT_AUTH,
]),
critical=False,
)

# Basic constraints (not a CA)
builder = builder.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True,
)

certificate = builder.sign(
private_key=ca_private_key,
algorithm=hashes.SHA256(),
)

with open("certs/server.crt", "wb") as f:
f.write(certificate.public_bytes(serialization.Encoding.PEM))

with open("certs/server.key", "wb") as f:
f.write(server_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))


print("Certificates generated successfully in the 'certs' directory")
print("\nTo trust these certificates:")
print("\nOn macOS:")
print("sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain certs/server.crt")
print("\nOn Windows (PowerShell as Admin):")
print("Import-Certificate -FilePath \"certs\\server.crt\" -CertStoreLocation Cert:\\LocalMachine\\Root")
print("\nOn Linux:")
print("sudo cp certs/server.crt /usr/local/share/ca-certificates/proxy-pilot.crt")
print("sudo update-ca-certificates")
print("\nFor VSCode, add to settings.json:")
print('''{
"http.proxy": "https://localhost:8989",
"http.proxySupport": "on",
"github.copilot.advanced": {
"debug.testOverrideProxyUrl": "https://localhost:8989",
"debug.overrideProxyUrl": "https://localhost:8989"
}
}''')

if __name__ == "__main__":
generate_certificates()
21 changes: 19 additions & 2 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

# Network settings
port: 8989 # Port to listen on (1-65535)
proxy_port: 8990 # Proxy port to listen on (1-65535)
host: "localhost" # Host to bind to (use localhost for all interfaces)

# Logging configuration
log_level: "INFO" # One of: ERROR, WARNING, INFO, DEBUG

# Note: This configuration can be overridden by:
# 1. CLI arguments (--port, --host, --log-level)
# 2. Environment variables (CODEGATE_APP_PORT, CODEGATE_APP_HOST, CODEGATE_APP_LOG_LEVEL)
# 1. CLI arguments (--port, --proxy-port, --host, --log-level)
# 2. Environment variables (CODEGATE_APP_PORT, CODEGATE_APP_PROXY_PORT, CODEGATE_APP_HOST, CODEGATE_APP_LOG_LEVEL)

# Provider URLs
provider_urls:
Expand All @@ -26,6 +27,22 @@ provider_urls:
# --openai-url
# --anthropic-url

# Certificate configuration
certs_dir: "./certs" # Directory for certificate files
ca_cert: "ca.crt" # CA certificate file name
ca_key: "ca.key" # CA key file name
server_cert: "server.crt" # Server certificate file name
server_key: "server.key" # Server key file name

# Note: Certificate configuration can be overridden by:
# 1. CLI arguments (--certs-dir, --ca-cert, --ca-key, --server-cert, --server-key)
# 2. Environment variables:
# CODEGATE_CERTS_DIR
# CODEGATE_CA_CERT
# CODEGATE_CA_KEY
# CODEGATE_SERVER_CERT
# CODEGATE_SERVER_KEY

# Embedding model configuration

####
Expand Down
70 changes: 70 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The configuration system in Codegate is managed through the `Config` class in `c
## Default Configuration Values

- Port: 8989
- Proxy Port: 8990
- Host: "localhost"
- Log Level: "INFO"
- Log Format: "JSON"
Expand All @@ -21,6 +22,12 @@ The configuration system in Codegate is managed through the `Config` class in `c
- OpenAI: "https://api.openai.com/v1"
- Anthropic: "https://api.anthropic.com/v1"
- Ollama: "http://localhost:11434"
- Certificate Configuration:
- Certs Directory: "./certs"
- CA Certificate: "ca.crt"
- CA Key: "ca.key"
- Server Certificate: "server.crt"
- Server Key: "server.key"

## Configuration Methods

Expand All @@ -35,6 +42,7 @@ config = Config.from_file("config.yaml")
Example config.yaml:
```yaml
port: 8989
proxy_port: 8990
host: localhost
log_level: INFO
log_format: JSON
Expand All @@ -43,13 +51,19 @@ provider_urls:
openai: "https://api.openai.com/v1"
anthropic: "https://api.anthropic.com/v1"
ollama: "http://localhost:11434"
certs_dir: "./certs"
ca_cert: "ca.crt"
ca_key: "ca.key"
server_cert: "server.crt"
server_key: "server.key"
```

### From Environment Variables

Environment variables are automatically loaded with these mappings:

- `CODEGATE_APP_PORT`: Server port
- `CODEGATE_APP_PROXY_PORT`: Server proxy port
- `CODEGATE_APP_HOST`: Server host
- `CODEGATE_APP_LOG_LEVEL`: Logging level
- `CODEGATE_LOG_FORMAT`: Log format
Expand All @@ -58,13 +72,41 @@ Environment variables are automatically loaded with these mappings:
- `CODEGATE_PROVIDER_OPENAI_URL`: OpenAI provider URL
- `CODEGATE_PROVIDER_ANTHROPIC_URL`: Anthropic provider URL
- `CODEGATE_PROVIDER_OLLAMA_URL`: Ollama provider URL
- `CODEGATE_CERTS_DIR`: Directory for certificate files
- `CODEGATE_CA_CERT`: CA certificate file name
- `CODEGATE_CA_KEY`: CA key file name
- `CODEGATE_SERVER_CERT`: Server certificate file name
- `CODEGATE_SERVER_KEY`: Server key file name

```python
config = Config.from_env()
```

## Configuration Options

### Network Settings

Network settings can be configured in several ways:

1. In Configuration File:
```yaml
port: 8989 # Port to listen on (1-65535)
proxy_port: 8990 # Proxy port to listen on (1-65535)
host: "localhost" # Host to bind to
```

2. Via Environment Variables:
```bash
export CODEGATE_APP_PORT=8989
export CODEGATE_APP_PROXY_PORT=8990
export CODEGATE_APP_HOST=localhost
```

3. Via CLI Flags:
```bash
codegate serve --port 8989 --proxy-port 8990 --host localhost
```

### Provider URLs

Provider URLs can be configured in several ways:
Expand Down Expand Up @@ -95,6 +137,33 @@ Note:
- For the vLLM provider, the /v1 path is automatically appended to the base URL if not present.
- For the Ollama provider, the /api path is automatically appended to the base URL if not present.

### Certificate Configuration

Certificate files can be configured in several ways:

1. In Configuration File:
```yaml
certs_dir: "./certs"
ca_cert: "ca.crt"
ca_key: "ca.key"
server_cert: "server.crt"
server_key: "server.key"
```

2. Via Environment Variables:
```bash
export CODEGATE_CERTS_DIR=./certs
export CODEGATE_CA_CERT=ca.crt
export CODEGATE_CA_KEY=ca.key
export CODEGATE_SERVER_CERT=server.crt
export CODEGATE_SERVER_KEY=server.key
```

3. Via CLI Flags:
```bash
codegate serve --certs-dir ./certs --ca-cert ca.crt --ca-key ca.key --server-cert server.crt --server-key server.key
```

### Log Levels

Available log levels (case-insensitive):
Expand Down Expand Up @@ -160,6 +229,7 @@ prompt = config.prompts.prompt_name
The configuration system uses a custom `ConfigurationError` exception for handling configuration-related errors, such as:

- Invalid port numbers (must be between 1 and 65535)
- Invalid proxy port numbers (must be between 1 and 65535)
- Invalid log levels
- Invalid log formats
- YAML parsing errors
Expand Down
Loading