---
sidebar_position: 5
title: Hetzner Object Storage
description: Configure MotherDuck to read files from Hetzner Object Storage using S3-compatible credentials.
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import CloudExecutionCallout from "./_cloud-execution-callout.mdx";

## Configure Hetzner Object Storage credentials

You can safely store your Hetzner Object Storage credentials in MotherDuck for convenience by creating a `SECRET` object using the [CREATE SECRET](/sql-reference/motherduck-sql-reference/create-secret.md) command.

:::note
See [Hetzner docs](https://docs.hetzner.com/storage/object-storage/getting-started/generating-s3-keys/) to create S3 access keys. Save your secret key immediately as it cannot be viewed again after creation.
:::

### Create a SECRET object

<Tabs>
<TabItem value="sql" label="SQL">

```sql
CREATE SECRET IN MOTHERDUCK (
    TYPE S3,
    KEY_ID 'your_access_key', # provided by Hetzner
    SECRET 'your_secret_key', # provided by Hetzner
    ENDPOINT 'fsn1.your-objectstorage.com', # provided by Hetzner
    SCOPE 'your_bucket_scope' # Example: s3://test-bucket
);
```

:::note
The endpoint must include the location (e.g., fsn1, nbg1, or hel1). Available endpoints:
- `fsn1.your-objectstorage.com` (Falkenstein)
- `nbg1.your-objectstorage.com` (Nuremberg)
- `hel1.your-objectstorage.com` (Helsinki)
:::

```sql
-- test the Hetzner Object Storage credentials
SELECT count(*) FROM 's3://[bucket]/[file]'
```

</TabItem>

<TabItem value="python" label="Python">

```python

import duckdb

con = duckdb.connect('md:')
con.sql("CREATE SECRET IN MOTHERDUCK ( TYPE S3, KEY_ID 'your_access_key', SECRET 'your_secret_key', ENDPOINT 'fsn1.your-objectstorage.com', SCOPE 'your_bucket_scope' )");

# testing that our Hetzner credentials work
con.sql("SELECT count(*) FROM 's3://[bucket]/[file]'").show()
```

</TabItem>

<TabItem value="ui" label="UI">

Click on your profile to access the `Settings` panel and click on `Secrets` menu.

![menu_1](./img/settings_access.png)
![menu_2](./img/settings_panel.png)

Then click on `Add secret` in the secrets section.

![menu_3](./img/settings_secrets_panel.png)

Select the Secret Type `S3` and fill in the required fields. Ensure you add the endpoint URL (e.g., `fsn1.your-objectstorage.com`) in the endpoint field.

</TabItem>
</Tabs>


### Delete a SECRET object

<Tabs>
<TabItem value="sql" label="SQL">

You can use the same method above, using the [DROP SECRET](/sql-reference/motherduck-sql-reference/delete-secret.md) command.

```sql
DROP SECRET <secret_name>;
```

</TabItem>

<TabItem value="ui" label="UI">
Click on your profile and access the `Settings` menu. Click on the bin icon to delete the secret.

![menu_4](./img/secrets_delete_azure.png)

</TabItem>

</Tabs>

### Hetzner Object Storage credentials as temporary secrets

MotherDuck supports DuckDB syntax for providing Hetzner Object Storage credentials.

```sql
CREATE SECRET (
    TYPE S3,
    KEY_ID 'your_access_key',
    SECRET 'your_secret_key',
    ENDPOINT 'fsn1.your-objectstorage.com',
    SCOPE 'your_bucket_scope'
);
```

:::note
Local/In-memory secrets are not persisted across sessions.
:::

<CloudExecutionCallout provider="Hetzner Object Storage" />

### Multiple locations configuration

If you have buckets in different Hetzner locations, you should be creating scoped secrets:

```sql
-- Secret for Falkenstein location
CREATE SECRET hetzner_fsn1 IN MOTHERDUCK (
    TYPE S3,
    KEY_ID 'access_key_1',
    SECRET 'secret_key_1',
    ENDPOINT 'fsn1.your-objectstorage.com',
    SCOPE 's3://my-bucket-fsn1'
);

-- Secret for Nuremberg location
CREATE SECRET hetzner_nbg1 IN MOTHERDUCK (
    TYPE S3,
    KEY_ID 'access_key_2', 
    SECRET 'secret_key_2',
    ENDPOINT 'nbg1.your-objectstorage.com',
    SCOPE 's3://my-bucket-nbg1'
);
```

:::tip
By default, each key pair is automatically valid for every bucket within the same Hetzner project. Use bucket policies to restrict access if needed.
:::
