{% extends "base.html" %} {% block title %}Add asset · {{ ['Connect','Identity','Relationships','Provision & Verify','Review & Add'][draft.stage - 1] }}{% endblock %} {% block content %}

Add supported asset

{{ ['Connect','Identity','Relationships','Provision & Verify','Review & Add'][draft.stage - 1] }}

Your progress is saved automatically.

{{ 'Verified' if draft.preflight_passed_at else 'Draft saved' }}
{% if error and draft.stage != 4 %}{% endif %} {% if draft.stage == 1 %}

Choose the device family

Choose the platform you are connecting.

{% if single_ecosystem %}
This asset will be added to {{ single_ecosystem.name }}.
{% else %}

Choose the existing NEXXVU environment that will contain this asset.

{% endif %}
Platform / device family

Choose the device family. NEXXVU detects its exact version.

{% for item in platform_choices %}{% endfor %}
Supported versions

NEXXVU detects the device version and selects the matching supported version.

{% for item in templates %}

{{ item.platform }} — {{ item.version_label }}

{% endfor %}

Select a platform to see its supported versions.

{% elif draft.stage == 2 %}

Name and organize this asset

Choose clear inventory names and optional operator context.

Inventory name, such as “NODE12”. Maximum {{ field_limits.name }} characters.

Optional friendly name. Maximum {{ field_limits.display_name }} characters.

Short purpose or responsibility. Maximum {{ field_limits.summary }} characters.

Additional details (optional)

Optional operational context. Maximum {{ field_limits.description }} characters.

Location (optional)
{% if locations %}

Select a saved location or leave this empty.

{% else %}

No saved locations are available.

{% endif %}

The asset’s main function. This does not grant access permissions.

Categories (optional)

Reusable labels for grouping this asset.

{% for item in categories %}{% else %}

No categories are configured.

{% endfor %}
{% elif draft.stage == 3 %}

Place and relate this asset

Only compatible assets are shown.

{% set selected_parent = draft.data.parent_asset_id or relationship_candidates.default_parent_id %}

Placement

Belongs to

The cluster, site or container this asset belongs to.

{% for item in relationship_candidates.parent if item.id == selected_parent %}{{ item.display_name or item.name }}{{ item.role|replace('-',' ')|title }}{% else %}No parent asset selected{% endfor %}
Find / Change parent
{% for item in relationship_candidates.parent %}{% endfor %}
{% for relationship_type, group_label, operator_label in [('runs_on','Hosting','Runs on / Hosted on'),('connected_through','Network','Connected through'),('monitored_by','Monitoring','Monitored by')] %}{% if relationship_type not in relationship_candidates.not_applicable %}{% set selected_ids = selected_relationships.get(relationship_type, []) %}{% set is_single = relationship_type in ['runs_on','connected_through'] %}

{{ group_label }}

{{ operator_label }}

{{ relationship_guidance[relationship_type].help }}

{% for item in relationship_candidates[relationship_type] if item.id in selected_ids %}{{ item.display_name or item.name }}{{ item.role|replace('-',' ')|title }}{% else %}No {{ operator_label|lower }} assets added{% endfor %}
Find / Add
{% if is_single %}{% endif %}{% for item in relationship_candidates[relationship_type] %}{% endfor %}
{% endif %}{% endfor %}
Advanced relationships (optional)
{% for relationship_type, operator_label in [('communicates_with','Communicates with'),('depends_on','Depends on')] %}{% set selected_ids = selected_relationships.get(relationship_type, []) %}

{{ operator_label }}

{{ relationship_guidance[relationship_type].help }}

{% for item in relationship_candidates[relationship_type] if item.id in selected_ids %}{{ item.display_name or item.name }}{% else %}{% if relationship_type == 'depends_on' %}No dependencies added{% else %}No {{ operator_label|lower }} assets added{% endif %}{% endfor %}
Find / Add
{% for item in relationship_candidates[relationship_type] %}{% endfor %}
{% endfor %}
{% elif draft.stage == 4 %} {% if template.platform == 'Proxmox' %} {% set inspection = draft.data.proxmox_inspection or {} %} {% set plan = draft.data.proxmox_plan or {} %}

Connect, provision and verify

{% if error %}{% endif %} {% if not inspection %}

Use temporary administrator access once so NEXXVU can identify this Proxmox system and prepare a least-privilege monitoring plan.

{% set connection_form = draft.data.proxmox_connection_form or {} %}
Temporary administrator access

Used temporarily and not saved. Enter the password again after resuming a draft.

Enter one IP address or hostname only—no scheme, path or credentials.

A number from 1 to 65535. Proxmox HTTPS API normally uses 8006.

Use Proxmox user@realm format, for example root@pam.

Used temporarily and not saved.

NEXXVU monitoring access

NEXXVU will create or reuse this dedicated account on the Proxmox server for ongoing read-only monitoring. The temporary administrator account above is used only to provision and verify it.

{% set durable_username = connection_form.durable_service_username or draft.data.durable_service_username or proxmox_service_user %}{% if draft.data.proxmox_edit_durable_identity %}

Use Proxmox user@realm format. NEXXVU will re-inspect the device and show a new plan before making changes.

{% else %}
Durable NEXXVU monitoring identity
{{ durable_username }}
Access type
Read-only monitoring
{% endif %}
{% else %}
Reachable and authenticated{{ inspection.platform }} {{ inspection.version }} · node {{ inspection.node }}{% if inspection.cluster %} · cluster {{ inspection.cluster }}{% endif %}
Detected platform
{{ inspection.platform }} {{ inspection.version }}
Compatible supported version
{{ template.version_label }}
Device identity
{{ inspection.node }}{% if inspection.cluster %} in {{ inspection.cluster }}{% endif %}
Certificate trust
Verified
Technical connection details
Public TLS fingerprint
{{ inspection.certificate_sha256 }}
{% if draft.data.provisioning_receipt and draft.data.provisioning_state == 'failed' %}
Provisioning stopped safely. {{ draft.data.provisioning_receipt.failure_message }} Completed operations are recorded below; the final Asset was not created.
{% endif %} {% if draft.data.provisioning_state in ['plan_ready','failed'] %}

Provisioning plan

Create a read-only NEXXVU monitoring identity, grant monitoring access, create its API token, and verify it works.

Durable NEXXVU monitoring identity
{{ plan.service_user }}
Access type
Read-only monitoring
Technical plan details

{{ plan.summary }}

{% if plan.reused %}

Existing configuration to reuse

    {% for item in plan.reused %}
  • {{ item }}
  • {% endfor %}
{% endif %}

Approved changes

    {% for item in plan.operations %}
  1. {{ item }}
  2. {% endfor %}

Verification after provisioning

    {% for item in plan.verification %}
  • {{ item }}
  • {% endfor %}

The API token uses privilege separation. Effective access is the intersection of the dedicated user and token ACLs.

Monitoring capabilities

Available capabilities come from the detected platform and compatible supported version.

{% for item in template.dashboard_capabilities if item.capability_id in inspection.capabilities %}{% endfor %}
Advanced monitoring details

Collectors and binding identifiers remain repository-controlled and are not editable here.

Approve temporary administrator use

Re-enter the temporary password to authorize this fixed plan. NEXXVU verifies the durable monitoring identity before discarding it.

Temporary administrator: {{ draft.data.bootstrap_username }}

Used temporarily and not saved.

{% else %}
NEXXVU monitoring access verified. The temporary administrator credential was discarded.
{% endif %} {% endif %}
{% else %} {% set managed_routeros_import = stage_four_auth_mode == 'managed_routeros' and (not routeros_managed_profile or routeros_replacing) %} {% set pending_auth = draft.data.pending_authentication_profile or {} %}

Connect, provision and verify

{% if error %}{% endif %}
Read-only connection verification: this platform flow verifies approved existing monitoring access and does not modify the target.

NEXXVU shows only connection methods approved for {{ template.platform }}. Verification uses a bounded timeout and does not change the target.

{{ template.platform }}
Approved compatibility: {{ template.version_label }}

{% if setup_guidance %}
{{ setup_guidance.title }}

Operator-executed preparation only. NEXXVU does not run these commands, configure RouterOS, create device credentials or grant permissions.

    {% for item in setup_guidance.steps %}
  1. {{ item }}
  2. {% endfor %}

Placeholder-only RouterOS terminal template

Review and replace every angle-bracket placeholder on RouterOS. Run only under Hani #1’s change authority.

{{ setup_guidance.routeros_template }}

Secret warning: Set <SET_ON_ROUTER_ONLY> on RouterOS. Never paste a password, token, private key or other secret value into ordinary wizard fields; use only the managed workflow’s write-only password control.

Provision protected Portal references

    {% for item in setup_guidance.portal_file_steps %}
  1. {{ item }}
  2. {% endfor %}

Enter these values in NEXXVU

{% for label, value in setup_guidance.nexxvu_entries %}
{{ label }}
{{ value }}
{% endfor %}

Preflight then uses HTTPS GET access to /rest/interface with the selected destination port, verifies the certificate chain and hostname/SAN using the CA reference, and reads authentication only through the protected password-file reference.

{% endif %}

Destination address reached by the Portal. Enter only the host or IP, without a URL scheme, path or credentials.

{% for connection in connection_options %}

Approved {{ connection.protocol|upper }} connection for {% for collector in connection.collector_types %}{{ collector }}{% if not loop.last %}, {% endif %}{% endfor %}. Default destination port {{ connection.default_port }}{% if connection.path %}, read-only path {{ connection.path }}{% endif %}. Override the port only when the operator configured a different destination such as 9443.

{% endfor %}
Credentials

Use a saved credential or add an approved credential reference. Assets store only a protected Auth Profile reference—never a secret value. A resumed draft requires credential input again whenever a secret is needed.

{% if stage_four_auth_mode == 'existing' %}

Only compatible active credentials backed by protected file references are shown.

{% for item in authentication_profiles %}
{{ item.label }} compatibility and reference metadata
Type / capability
{{ item.auth_capability }}
Protocol
{{ item.protocols|join(', ')|upper }}
Username
{{ item.username or 'Not applicable' }}
Configured references
{% for reference in item.secret_references %}Configured {{ reference.label }} file reference: {{ reference.path }}{% if not loop.last %}
{% endif %}{% endfor %}

These paths are configured profile metadata. This compatibility view does not verify file existence or readability; access is validated during preflight and runtime use.

{% endfor %} {% elif stage_four_auth_mode == 'managed_routeros' %}

Add RouterOS credential

Use the guided setup to create protected monitoring access. NEXXVU validates the resulting read-only connection.

Download RouterOS setup script

{% if routeros_managed_profile %}
Managed references configured. Profile {{ routeros_managed_profile.name }} for username {{ routeros_managed_profile.username }}. Public CA SHA-256 fingerprint: {{ routeros_ca_sha256 }}. The password was stored write-only and is not displayed.
{% endif %} {% if not routeros_managed_profile or routeros_replacing %}{% if routeros_replacing %}{% endif %}

Safe operator-facing label for the automatically created RouterOS authentication-profile metadata.

The same dedicated read,api,rest-api username configured by the downloaded script.

Upload one PEM public CA certificate, at most 16 KiB. Basic Constraints must authorize CA signing; certificate-signing Key Usage is enforced when present. During replacement, leave this empty to retain the configured CA. Target chain and hostname/SAN remain validated by HTTPS preflight.

{{ 'Provide a new password or leave empty to retain the protected configured value.' if routeros_replacing else 'Enter the password set locally on RouterOS.' }} A submitted password is written to an application-controlled 0600 file, never stored in the draft and never redisplayed.

{% elif routeros_managed_profile %}

Replace managed CA or password

{% endif %} {% else %}

Add a durable credential reference for monitoring access already provisioned on the target.

Operator-facing label for recognizing this saved credential.

Only types compatible with the selected platform are available.

{% for schema in authentication_profile_schemas %}{% if schema.username_required %}

Username already created on the target. Enter no password here.

{% endif %}{% for key in schema.secret_ref_keys %}

Reference to an existing protected file under /etc/nexxvu-portal. Secret values are never displayed or saved in this draft.

{% endfor %}{% endfor %} {% endif %}
Monitoring capabilities

Choose the approved read-only information NEXXVU should monitor. Internal binding details remain repository-controlled.

{% for item in template.dashboard_capabilities %}{% endfor %}
Advanced monitoring details
{% for item in template.dashboard_capabilities %}

{{ item.binding_id }}

{% endfor %}
{% if managed_routeros_import %}

{{ 'Replacement validates and writes a complete new protected file set before the previous files are removed.' if routeros_replacing else 'Import creates bounded protected references only.' }} After import, review the fingerprint and verify again.

{% else %}

Verify after reviewing the target, port, credential and monitoring capabilities. Failure preserves every non-secret field shown here. Credential values are never saved in the draft or redisplayed.

{% endif %}
{% if routeros_managed_profile %}
{% endif %}
{% endif %} {% elif draft.stage == 5 %}

Review before adding

Confirm the operator-facing identity, relationships, connection, saved credential reference and monitoring choices before the Asset is created.

{% if draft.data.provisioning_state == 'verified' %}
Durable NEXXVU monitoring access was provisioned and verified independently.
{% else %}
No target provisioning was performed. The verification result below comes from the approved read-only connection check.
{% endif %} {% if (draft.data.credential_cleanup or {}).status == 'pending' %}
Obsolete credential cleanup is pending. The new verified monitoring access is active and this review remains valid. Re-enter temporary administrator access to retry removal of the retired token and protected file.

Used temporarily and not saved.

{% elif (draft.data.credential_cleanup or {}).status == 'complete' %}
Retired monitoring credentials were removed successfully.
{% endif %}
Environment
{{ single_ecosystem.name if single_ecosystem else draft.data.ecosystem_id }}
Asset name
{{ draft.data.name }}
Display name
{{ draft.data.display_name }}
Summary
{{ draft.data.summary or 'Not supplied' }}
Additional details
{{ draft.data.description or 'Not supplied' }}
Platform
{{ (draft.data.proxmox_inspection or {}).platform or template.platform }}{% if (draft.data.proxmox_inspection or {}).version %} {{ draft.data.proxmox_inspection.version }}{% endif %}
Supported version
{{ template.version_label }}
Device identity
{{ (draft.data.proxmox_inspection or {}).node or draft.data.host }}{% if (draft.data.proxmox_inspection or {}).cluster %} · {{ draft.data.proxmox_inspection.cluster }}{% endif %}
Primary role
{{ draft.data.role }}
Categories
{% for item in review.categories %}{{ item.name }}{% if not loop.last %}, {% endif %}{% else %}None{% endfor %}
Location
{{ review.location_name or 'Not set' }}
Belongs to
{{ review.parent_name or 'No parent asset' }}
Relationships
{% for item in review.relationships %}{{ {'runs_on':'Runs on / Hosted on','connected_through':'Connected through','monitored_by':'Monitored by','communicates_with':'Communicates with','depends_on':'Depends on'}.get(item.relationship_type, item.relationship_type|replace('_',' ')|title) }}: {{ item.target_name }}{% if not loop.last %}
{% endif %}{% else %}None{% endfor %}
Target
{{ draft.data.host }}
Connection
{% for protocol, port in draft.data.ports|dictsort %}{{ protocol|upper }} on destination port {{ port }}{% if not loop.last %}
{% endif %}{% endfor %}
{% if draft.data.provisioning_state == 'verified' %}
Temporary administrator
{{ draft.data.bootstrap_username }} · used only during provisioning
Durable NEXXVU monitoring identity
{{ proxmox_service_user }}
{{ proxmox_access_label }}
{% endif %}
NEXXVU monitoring access
{{ draft.data.authentication_profile_label }} · {{ draft.data.authentication_profile_type }}
Monitoring capabilities
{% for item in template.dashboard_capabilities if item.binding_id in draft.data.binding_ids %}{{ capability_labels[item.capability_id] }}{% if not loop.last %}
{% endif %}{% endfor %}
{% if draft.data.provisioning_receipt %}
Provisioning performed
{% for item in draft.data.provisioning_receipt.created %}Created {{ item }}{% if not loop.last %}
{% endif %}{% endfor %}{% for item in draft.data.provisioning_receipt.reused %}Reused {{ item }}{% if not loop.last %}
{% endif %}{% endfor %}
Provisioned at
{{ draft.data.provisioning_receipt.recorded_at }}
{% endif %}
Verification
Succeeded {{ draft.data.preflight_summary }}
{% if draft.data.provisioning_state == 'verified' %}

Editing provisioning settings returns to inspection and requires a new plan, explicit approval, reconciliation and independent verification before this review is available again.

{% endif %} {% if proxmox_verification_commands %}
Verify directly in Proxmox

Run these read-only listing and permission checks in an authorized Proxmox shell. They verify the exact NEXXVU user, role, ACL, token, privilege separation and effective permissions. They do not reveal the token secret and do not replace NEXXVU’s verification.

{% for command in proxmox_verification_commands %}{{ command }}{% if not loop.last %}
{% endif %}{% endfor %}

Confirm user {{ proxmox_service_user }}, role {{ proxmox_role }}, token {{ proxmox_token_id }}, privilege separation enabled, and audit/read-only effective permissions.

{% endif %} {% if (draft.data.proxmox_inspection or {}).fingerprint %}
Technical identity details
Device fingerprint
{{ draft.data.proxmox_inspection.fingerprint }}
Public TLS fingerprint
{{ draft.data.proxmox_inspection.certificate_sha256 }}
{% endif %}

The Asset remains the authoritative inventory record. The saved credential remains an Auth Profile reference; no secret value is copied to the Asset.{% if (draft.data.credential_cleanup or {}).status == 'pending' %} Complete the cleanup retry above before adding this asset.{% endif %}

{% endif %}
{% endblock %} {% block scripts %}{% endblock %}